On 12/31/12 1:39 PM, Marcus G. Daniels wrote:
Of course, there is rarely the time or incentive structure to do any of
this. Productive programmers are the ones that get results and are fast
at fixing (and creating) bugs. In critical systems, at least, that's
the wrong incentive structure. In these situations, it's more important
to reward people that create tests, create internal proofs, and refactor
and simplify code. Having very dense code that requires investment to
change is a good thing in these situations.
Programming for the broadcasting industry right now (where a few seconds
downtime might cost millions of dollars), I especially liked your point,
Marcus. I live within this tension every day, as I imagine so do to an
even higher degree aircraft software designers, medical system
designers, automotive software designers, and so on where many lives are
at risk from a bug. Certainly the more unit tests that code has, the
more "dense" the code might feel, as the more resistant to casual change
it can become, even as one may be ever more assured that the code is
probably doing what you expect most of the time. And the argument goes
that such denseness in terms of unit tests may actually give you more
confidence in refactoring. But I can't say I started out feeling or
programming that way.
The movie "The Seven Samurai" begins with the villagers having a big
conceptual problem. How do the agriculturalists know how to hire
competent Samurai, not being Samurai themselves? The villagers would
most likely be able to know the difference in a short time between an
effective and ineffective farm hand they might hire (based on their
agricultural domain knowledge) -- but what do farmers know about
evaluating swordsmanship or military planning? Likewise, an end user may
know lots about their problem domain, but how can users tell the
difference between effective and ineffective coding in the short term?
How can users distinguish between software that just barely works at
handling current needs and, by contrast, software that could handle a
broad variety of input data, which could be easily expandable, and which
would detect through unit tests unintended consequences of coding
changes? That is meant mostly rhetorically -- although maybe a more
on-topic question for this list would be how do we create software
systems that somehow help people more easily appreciate or understand or
visualize that difference?
Unless you know what to look for (and even sometimes if you do), it is
hard to tell whether a programmer spending a month or two refactoring or
writing tests is making the system better, or making the system worse,
or maybe just is not doing much at all. Even worse from a bean counter
perspective, what about the programmer who claims to be spending time
(weeks or months) just trying to *understand* what is going on? And
then, what if after apparently doing nothing for weeks, the programmer
then removes lots of code? How does one measure that level of apparent
non-productivity or even negative-productivity? A related bit of history:
http://c2.com/cgi/wiki?NegativeLinesOfCode
"A division of AppleComputer started having developers report
LinesOfCode written as a ProductivityMetric?. The guru, BillAtkinson,
happened to be refactoring and tuning a graphics library at the time,
and ended up with a six-fold speedup and a much smaller library. When
asked to fill in the form, he wrote in NegativeLinesOfCode. Management
got the point and stopped using those forms soon afterwards."
If there is a systematic answer, part of it might be in having lots of
different sorts of metrics for code, like in the direction of projects
like "Sonar". I don't see Sonar mentioned on this list, at least in the
past six or so years. Here is a link:
http://www.sonarsource.org/
"Sonar is an open platform to manage code quality. As such, it covers
the 7 axes of code quality: Architecture & Design, Comments, Coding
rules, Potential bugs, Complexity, Duplications, and Unit tests"
We tend to get what we measure. So, are these the sorts of things new
computing efforts should be measuring?
Obviously, users can generally see the value of new functionality,
especially if they asked for it. And thus there is this tension between
infrastructure and functionality. This tension is especially strong in
the context of "black swan" situations where chances are some rare thing
will never happen, and if it does, someone else will be maintaining the
code by then. How does one create incentives (and supporting metrics)
related to that? In practice, this tension may sometimes get resolved by
spending some time on refactoring and tests that the user will not
appreciate directly and some time of obvious enhancements users will
appreciate. Of course, this will make the enhancements seem to take
longer than they might otherwise in the short term. And it can be an
organizational and personal challenge to interleave the two areas of
work (infrastructure and functionality) so the users stay happy enough.
Yet, I might argue, if you don't do the two in parallel, you may find
you are not creating either the needed infrastructure or the needed code.
"Agile" methods embrace the idea of coding for obvious functionality,
saying "You're not going to need it". But agile methods may also be more
appropriate in some situations than others. And agile methods do also
tend to celebrate and insist on refactoring and testing on the way to
creating new functionality, which when you think about it is an
odd-seeming way of addressing your point -- by a sort of "cultural"
approach. In that sense, Agile methods start with the best practices of
testing and refactoring as givens in an programming culture, and then
measures progress in terms of function points. But there is always going
to be the pressure to focus more on the function points and less on the
other things. And that might be where tools like Sonar help keep teams
from letting maintainability slide in the quest for new function points.
Maybe we need a language where code just won't compile unless it has
tests written for it in advance? :-) Was Eiffel heading that way with
"Design by Contract"? Or maybe we need to have more projects using tools
like Sonar, and write even better such tools, as well as better
languages to use with them? The message passing paradigm in Smalltalk
(making proxying and mocking easier) along with other aspects like
dynamic strong typing, means Smalltalk historically lent itself to
creating better tools and tests. Although there is still a tension in
that statically-typed systems also made some other sorts of reasoning
about programs easier to do. (Not to get into that discussion, which has
been hashed out on this list and in many other places before.)
Like Fred Brooks said in 1986:
http://en.wikipedia.org/wiki/No_Silver_Bullet
Or, as Kyle Wilson said in 2007:
http://gamearchitect.net/Articles/SoftwareIsHard.html
Still, we'd probably get software that was both more reliable and more
maintainable (as well as more fun to work with) if we just more commonly
used computing ideas (like message passing) that have been known for
decades. Or, for another example, Smalltalk's keyword syntax generally
makes for much more readable programs. Or for yet another example, Forth
could support a multi-user system doing real-time data collection, word
processing, and data analysis using just 32K bytes and a single 1 Mhz
processor, whereas many systems today struggle to be responsive for a
single user or single application when they have 32GB and 8 X 3 Ghz
processors. Indeed, do we need to go "Back to the future" again? :-)
--Paul Fernhout
http://www.pdfernhout.net/
====
The biggest challenge of the 21st century is the irony of technologies
of abundance in the hands of those thinking in terms of scarcity.
_______________________________________________
fonc mailing list
fonc@vpri.org
http://vpri.org/mailman/listinfo/fonc