
Hidden Costs That Engineers Ignore - gsands
http://www.theeffectiveengineer.com/blog/hidden-costs-that-engineers-ignore?utm_source=Founder+Weekly+Newsletter&utm_campaign=1a5eed15d1-Founder_Weekly_Issue_163_December_31_2014&utm_medium=email&utm_term=0_286b01fd3e-1a5eed15d1-331306269
======
mrlyc
What worked for us was to do two versions of the program at the same time.

Version one had simple functionality. Version two had all the bells and
whistles dreamt up by the programmers and the customer while we were working
on version one. Those were added to a todo list for version two. They were not
implemented in version one.

That kept up the flow of ideas but didn't disrupt the project. It made the
programmers feel appreciated while giving us an outline for the next version
so our competitors couldn't keep up.

What surprised me was that the whole team got into the spirit of the thing.
When someone came to me with an idea, cries of "Version two! Version two!"
echoed around the programming room.

~~~
Kiro
We were doing something similar but the result was a mess. Sometimes version 1
needed something that depended on unreleased stuff in version 2. It lead to
fragmentation where we developed two implementations of the same
functionality.

------
jonpress
The problem is that as requirements grow, class structures are often kept the
same but the 'glue logic' which operates on these structures becomes
increasingly complex (you have to handle a growing number of edge cases).

There is a point where the glue logic becomes very complex (and brittle) - At
that point, the best thing to do is to redesign part of the system's class
structure.

If your components (at all levels of your class hierarchy) are specific about
their own behaviors, it means that you can use simpler glue logic to make them
work together.

When you need to handle a lot of complex use cases, it's often useful to have
many specific classes which share the same interface and can be used
interchangeably.

~~~
cam-
If we get several bugs or the team recognizes that an area is becoming brittle
we make a bug that one/two team members work on for the sprint to clean that
entire area up. The PO has become used to these kinds of bugs/user-stories and
prioritizes them.

------
saosebastiao
Unfortunately, sometimes the simpler system is the one you don't yet
understand, and the more complex system is the one you can create on your own
using tools you do know. This is the reason we still see homegrown business
rule systems despite the fact that they were pretty much perfected them by the
late 70s, with several open source implementations as of the late 90s. It is
also the reason you still see deadlocks and race conditions in parallel code.
And it is the reason you see matrix factorizations using hadoop map reduce
instead of MPI.

And when these bullshit foundational design decisions are made, the
"improvements" that the engineers make to the system later are almost always a
reduction in fidelity to the real world process that is being modeled, instead
of a move toward a system that drastially simplifies your system while
simultaneously improving fidelity to the real world but might mean you have to
read a wikipedia article for a few minutes.

------
wavegeek
There is a good book about this. It changed my thinking about complexity. The
key insight is that if you don't manage complexity you will drown in it.
Complexity is OK as long as it really earns its keep. And a lot of complexity
is not worth it. (I speak as a person who just spent 20 hours - less than the
IRS's estimated 30 hours - filling in form W-8IMY for the IRS, a form which
started as a bright idea by someone in congress).

"Conquering Complexity in Your Business: How Wal-Mart, Toyota, and Other Top
Companies Are Breaking Through the Ceiling on Profits and Growth Paperback" by
Michael L. George and Stephen A. Wilson

~~~
codezero
Thanks for this, very interesting, I'll give it a read. I've long wondered if
the aversion to complexity in SV is at times pathological, that is, "it adds
complexity" is often used as a reason not to commit to building something that
would absolutely add long term benefits that outweigh the costs. I guess it's
just harder to quantify potential future benefits against immediately obvious
complexity, but all the same, I think pathologically avoiding complexity is
just as bad as pathological complexity :)

------
zedpm
The notion of holding a Code Purge Day (as Quora did) is excellent. Searching
out and removing cruft in the code base results in a benefit that's hard to
measure but easy to understand. Having more compact code without confusing
distractions leads to easier comprehension and ought to make for faster bug
fixes.

~~~
aswanson
Exactly. The best line of code is the one you dont have to write. The second
best is the one you can delete.

~~~
hawkice
My favorite aphorism for this is "There's no code like no code."

------
gaius
_Matching passengers and drivers while adjusting prices to balance supply and
demand is a complex and hard problem. So is routing questions and answers to
the people most likely to answer and read them_

I used to work with a guy who worked on the compute infrastructure that CERN
uses to sift the petabytes of data they get from the LHC. That's a hard
problem.

And that's the problem with web guys, they think the web is all of computing,
yield management has been done by airlines and hotels for DECADES. It is very,
very far from breaking novel ground at this point.

Now the points he makes about the TCO of a new feature are valid but please,
if you're going to brag, be prepared for people to yawn.

~~~
nmjohn
This point is quite nitpicky, no? The sentence you quoted could have been
removed from the article and the article would have largely been unchanged -
my point being it seems dubious to critique an article for a tangential point
in the introduction which has nothing to do with the premise of the article.

I think what it really is, is some people just like to complain about "web
guys" every opportunity they get. And while your criticism may have been
perfectly valid, it is entirely irrelevant to this article.

~~~
gaius
Not at all; the structure of the piece is, these are all the impressive things
I've done, so you should listen to my ideas. It would have been a stronger
piece of writing if he'd just jumped straight in. Or, actually had done some
impressive engineering.

There's a bit of ageism there too. Über's yield management code could probably
have been written by one grey haired guy from United Airlines or Marriott.
Instead they got a whole bunch of twenty something's who think they're doing
"data science".

------
seivan
You can't do this for games. Sometimes a game needs a particular feature that
has a ton of states and complexity.

The only thing you can do is 1)Mitigate that by isolate it 2)Separation of
concern

You could have a component that's fuck-all complex, but as long as it's a
single, isolated component, that can be disabled by

messedUpComponent.isEnabled = false, then I'm ok.

~~~
ars
> You can't do this for games.

Sure you can. For example people need to move around in the game. You can add
rideable objects - or not. Usually you don't need to ride something for the
game - it's just cool. So this is complexity you can remove.

You can take it a second step - assume riding is required. Do you want various
types? Say you ride a horse - do you need multiple colors and sizes of horses?

Or something as simple as allowing the character to change hats.

------
soup10
As a one man army indie game developer I basically can no longer maintain my
code-base without going crazy because it's grown to the point where it's no
longer a one man job. I knew this would be a problem, so keeping code
complexity to a minimum has always been a priority, but it's no longer
possible to keep up. Thankfully it's reached maturity as a product and is a
fun and profitable game. Many people think i'm 'brilliant' when they see the
product and they hear i'm the only the developer and it's a custom 3d engine.
But truth of the matter is much of my brilliance was stubbornness and
cleverness in keeping things simple and code complexity to a minimum. The
problem is you run out of memory in your brain. You forget how systems work.
You have to trace back through the code and "reload things". When you have to
make a modification.

When I hit my human ram capacity so to speak, i was extremely frustrated that
I couldn't make the boundlessly quick progress that I used to. But then you
get used to it, and just accept that it will take time when you switch from
one subsystem to the other, to load up the relevant parts of the code into
your human ram in order to do be able to do the work you want to do.

The simpler and more straightforward the program architecture, the easier it
is to jump into and out of and write new code. Of course understanding what
your product is and is going to be helps tremendously in making sure you can
design your program in a sensible way.... I've been lucky enough to have a
firm intuitive understanding of future the design of the game and it's
features as it was being formed. (not being at the mercy of clients or bad
managers is a wonderful thing)

What i've noticed is a big difference from me and friends with small
development studios that accomplish less with a lot more sweat. Is that I
don't develop fully featured flexible systems when simple ones will do, I
don't roll my own code when good/simple libraries or apis exist. I'm trying to
make my product a work of art, and the code is functional and simple. Where
often I see other good engineers try to make their code the work of art. Which
leads to lots unnecessary code complexity because they engineer systems
designed to be future proof for everything, instead of of what realistically
will be necessary for the future of the project or projects. A system with 30
components is easier to understand and easier to maintain than a system with
100. More functions, more objects, and more abstractions. Often mean more
components and code complexity. Which ultimately means it's going to take more
brainpower to get anything done. Which is why it takes teams of 100s to
maintain large enterprise software projects where the incremental updates
change very little even though the engineers working on it are educated well
trained people. _shrug_

~~~
jdmichal
> Which leads to lots unnecessary code complexity because they engineer
> systems designed to be future proof for everything, instead of of what
> realistically will be necessary for the future of the project or projects.

This has been a bane for me in my work. I have termed it lasagna code: lots of
layers with a little filling in between each. Often, each layer is isolating
things for which there is little-to-zero reason to ever suspect that they will
need to change. I've even seen attempts to abstract away data model... As if
the entire program wouldn't have to be modified if the data model changed. I
have learned to design and code only to known requirements. All the extra time
saved in design, coding, and maintenance of the easier reduced system more
than pays for the small redesigns necessary when things shift.

------
jaynate
In the world of enterprise software it's also easy to overlook the cost of
implementation/setup of features on the services teams and customers. Is
helpful to define nonfunctional requirements that deal with these ancillary
concerns.

Also all of these issues highlight why product management needs to have a
working knowledge of technology and the related costs of various trade offs.

------
sunasra
I am totally agree with 'Use data to prune unused features' point.

It might happened that some features were introduced years ago based on
demand. But It would be not usable for now. Still those features are
maintained. I believe those features should be removed which eventually gives
you space to work on innovative features for same product.

------
stefs
currently it looks like they ignored the hidden cost of being on the hn
frontpage.

------
logicallee
This article repeats a meme, but is total BS. It's similar to saying "the
hidden costs of being a founder" and then stating that if you do ever make a
successful exit, you will have a lot of your time wasted by having to select
bedlinen and other hidden costs of having made an exit. (the hidden cost to
being a founder - you will be forced to work unpaid hours shopping for luxury
bedlinen. so consider carefully.) Well guess what: that's not real technical
(or founder) debt!

The idea of calling this stuff technical debt is simply laughable. there's no
debt. you don't owe shit.

hint: if you code something up in 20 minutes you still don't have to do all
that other stuff, you can just ignore it, and throw away the twenty minutes of
code if it's not better than not having it. if you become a millionaire you
don't have to do all that stuff, you can just ignore it.

Let me put it another way. Say you're an MBA who can't code anything but excel
formulas, yet you figured out how to get excel and powerpoint onto the web as
a web app (wat). you create something and get 5,000 paying users and raise a
$500,000 investment.

Have you created technical debt? No. You're at the same square as if someone
gave you $500,000 to spend on developers against your mockups, except that
you've validated them as well. There's no debt here. This article had it
right:

[http://www.higherorderlogic.com/2010/07/bad-code-isnt-
techni...](http://www.higherorderlogic.com/2010/07/bad-code-isnt-technical-
debt-its-an-unhedged-call-option/)

The people that call this scenario (excel on the web) technical debt, think
that somehow the MBA 'borrowed' the web app from a real dev, and now owes it
in real development costs. That's a wrong way to think about it. In fact it's
a ridiculous way to think about it.

~~~
hw
While I agree with you that the notion of 'technical debt' is being overused,
I don't think the article is talking about hidden costs as technical debt, but
is instead about how product and code complexity incurs hidden costs, some of
which but not all can be construed as technical debt.

Code complexity is a good example. A part of a codebase can be complex
(sometimes the problem that is being solved necessitates a complex algorithm /
codebase) but yet well written. That does not incur technical debt, but there
is a hidden cost to maintain it given it's complex. On the other had, a
complex code base, that was done hackily in a few hours just to get to the
solution without any thought for maintainability or has no test coverage, is
technical debt, because the person 'borrowed' time amongst other things with
the hacked up codebase, which in the future he/she must pay down by
refactoring / writing tests.

~~~
chriswarbo
> A part of a codebase can be complex (sometimes the problem that is being
> solved necessitates a complex algorithm / codebase) but yet well written.

I tend to use the following terminology to distinguish necessary an
unnecessary complexity:

    
    
                      | Easy Problem | Hard Problem
        Easy Solution | Simple       | Simplistic
        Hard Solution | Complicated  | Complex

~~~
notduncansmith
Is a hard problem with an easy solution really a hard problem? A more accurate
chart might look like this:

    
    
                         | Simple Problem | Complex Problem
        Simple Solution  | Easy           | Elegant
        Complex Solution | Stupid         | Necessary

~~~
sbov
I think simplistic was meant to imply that it wasn't really a solution, just
good enough for you.

That said, you can say the same case for your matrix: if there's a simple
solution to a complex problem that actually solves it, is it really a complex
problem?

~~~
notduncansmith
Sure. "Complex" problems are problems with many facets/moving parts (I
recommend watching the Rich Hickey talk "Simple Made Easy"). These problems
can in some cases have simple (as in, few facets/moving parts) solutions,
although those solutions may not be easy to implement.

