
Fighting the Last War - keithba
http://keithba.net/fighting-the-last-war
======
venantius
One of the things that's interesting about this - and is good meat for further
discussion - is how to react when you find yourself on a team with someone
who's clearly fighting the last war. I think it's inevitable that people end
up fighting the last war, but I'd love to know if there are ways to break the
cycle for someone once you see it happening.

~~~
angersock
I'm kind of doing that right now--we've got that issue pretty badly, actually.
It's surmountable, but annoying.

Here are some observed causes or environmental factors:

 _Using an older or low-level language_. If you're doing code in
asm/C/C++/Matlab/Fortran (arguably Perl, PHP), odds are you aren't in a
position to easily pull in other people's solutions. That means that you are
probably trying to reinvent the wheel, because you don't know of a pre-
existing solution, because you don't want to pull in the massive baggage of
other solutions, or because you enjoy making the wheel over again yourself.
Newer, more abstract languages don't have this problem, mostly I think because
they come from a time of easy collaboration via the internet. The whole
gem/npm/hex ecosystems simply couldn't be possible without easy internet
access and github. I'm going to call out C++ specifically here, because using
that language with old code is terrible because odds are that, even if you are
doing things correctly, the library author isn't (from a strict software
engineering standpoint).

 _Not understanding your problem space_. Oftentimes, being overly conservative
about your design requirements (we must be webscale, fault tolerant,
absolutely _have_ to support XYZ vendor integration) means that you overdesign
--and when you do that, you are more likely to be fighting old wars. If you
really grok and have cleanly defined your problem space, you know where you
can cut corners, instead of overbuilding based on previous experience.

 _Not following de facto standards_. There's a bajillion ISO standards for
everything you might want, and a lot of people will glibly explain "The great
thing about standards is that there are so many to choose from". The problem
is, those people will either go on to ignore standards in favor of their own
(usually created to fight the last war), or pick one that isn't being used
(usually something that is fighting a war that was already won/lost). The only
thing worse than fighting the last war is fighting the last war from the
losing side. JSON vs XML is a great example of this, as is RFC3339 vs ISO8601
vs <insert wrong in-house way of doing time here>. Another great example is
REST vs SOAP, or Unix Way vs Not Unix Way, or ORM vs Not ORM.

 _Not being lazy_. The best wars are never fought, right? There's nothing
worse than a developer who is super industrious and never pauses to think
"Wait, is the problem I'm solving just a rehash of something I've done before,
or is there a deeper conflict here?". Fighting the last war happens when these
people continually reiterate on the last battle ("This time I've got time
right!", "This time I've got better performance!", "This time I've got the
right object model!"), all the while missing the important thing ("My customer
still can't do X").

 _Not sharing knowledge_. Probably the biggest one of these other than the
previous one is the problem of developers not letting other developers know
about what's been tried before, and why it did or did not work. We already
hate rehashing solutions--so if presented with a module that isn't explained,
are you going to rewrite it, or just accept it? Almost all the developers I
know would prefer to rewrite it (and only experience and wisdom holds them
back from doing so). When you've got a large codebase, and you've got like
three different exception handling systems built by different groups because
they don't talk, you've fought the last war three times.

------
Terr_
From working with an old PHP codebase, I'd like to offer: "Design for
deletion."

This has important differences from "design for modularity" or "design for
future change" or "design so someone can swap it out", because those phrases
tend to make developers go off and engineer extra stuff, under the assumption
that their current paradigm for how the software operates is going to continue
to be accurate even if their implementation someday needs replacing.

... But what happens when it's not just "this code sucks", but also "we
shouldn't even have any code that's doing this task"?

~~~
keithba
I love this idea. If you can easily delete the code, you can easily refactor!

~~~
Terr_
Thanks. When it comes to "easily refactor" I think there's a distinction to be
drawn between "hard but understandable and verifiable" versus "maybe-easy but
with unknown surprises."

The difficulty of replacing or refactoring code should come from the "inherent
complexity" of creating its replacement, not from the "incidental complexity"
of discovering its boundaries and influence.

------
lifeisstillgood
Nah ... not using async, not running with tests, these aren't "let's build a
Maginot line" mistakes. These are "let's not make sure our troops can run 10
miles and shoot accurately" mistakes.

Sure there are plenty of strategic mistakes that will doom any army or
enterprise - but the biggest one, the granddaddy of them all, is only
listening to half of the proverb "hire great people then get out of their way"

So many generals want to be sure everyone understands it is their clever
tactics that won the war they forget the lessons of generals who really do -
logistics and economics. Everything is subservient to getting a well fed and
trained soldier with a gun in his hand at the point he needs to be.

For a good example look at Spolsky - hiring good people, fixing up nice
offices, handing over lunch - probably there is some office manager who acts
as a general problem solver for the devs and magically makes boilers and
landlords and IRS problems vanish.

Logistics.

Not even big guns.

------
lmm
This is a problem of planning; I don't think more or more frequent planning is
the answer.

Instead you need to make the minimum viable thing, even more minimally. Make
sure the very first iteration is end-to-end usable to solve a real problem.
Then you'll notice if you can't use async on the backend before putting async
everywhere. You'll notice if you're testing too much. And you'll have a better
understanding of your burn rate because you've done all the tasks, including
the things like design and hosting and legal that can easily be forgotten.

------
SocksCanClose
Great article and topic. But just FYI, I don't think building a Maginot Line
actually qualifies as "fighting the last war". As the author explains, the ML
actually worked -- the Germans had to invade through Belgium! And had they
built the ML all the way to the sea, the blitzkrieg would have failed. Perhaps
a better historical military analogy would be that of Billy Mitchell and the
rise of Naval Aviation
([http://en.wikipedia.org/wiki/Naval_aviation#Interwar_period](http://en.wikipedia.org/wiki/Naval_aviation#Interwar_period)).
Anyway great lessons here -- thanks for posting.

~~~
tsotha
I groaned when I saw the Maginot Line thing yet again. People, your grade
school history teacher lied to you!

There was nothing wrong with the Maginot Line. As part of the overall plan
they intended to stop a German invasion through Belgium in Belgium. They had
an agreement with the Belgians which had Belgian troops using forts and
pillboxes to slow down the German invasion until French troops arrived.

But the French lost the war before it started when the Belgians decided they
didn't want to fight the next Great War in Belgium and pulled out of the
agreement. And they did so far too late for the French to make other
arrangements.

I like your reference to naval aviation, which is a much better fit.

~~~
23david
Interesting. Are there any references or good articles you've seen that go
into those details about Belgium? Never heard that before.

~~~
tsotha
The only one I can think of off the top of my head is Shirer's _The Rise and
Fall of the Third Reich_.

------
mattip
My take away from "Do just enough" is the flip side - throw it away and start
over. The second part is just as important as the first or you end up with
crap prototypes in the heart of your solution. The first time doesn't have
edge case handling and will be insecure, so toss it out when it starts to
become a product, if not before.

~~~
coldcode
You have to be willing to toss anything and everything if it isn't right. The
hard part is convincing the boss people that this isn't stupid at all.

~~~
PhantomGremlin
Similar advice is at least 40 years old. You could always point people at
Brooks: [http://en.wikipedia.org/wiki/The_Mythical_Man-
Month#The_pilo...](http://en.wikipedia.org/wiki/The_Mythical_Man-
Month#The_pilot_system)

Brooks says that you should probably _plan_ to do that. But almost nobody
does.

------
snarfy
> You need to watch the burn rate carefully, and have a clear plan for raising
> more money (either by selling to customers or raising from investors.)

Following the latter leads to the fatal pinch.

[http://www.paulgraham.com/pinch.html](http://www.paulgraham.com/pinch.html)

