I've wondered whether that is why we find ourselves surrounded by complex software. Legacy code is code that provides more value than the cost of its replacement. Bad code endures when that cost goes up.
2,516 karma · joined April 15, 2009
I've wondered whether that is why we find ourselves surrounded by complex software. Legacy code is code that provides more value than the cost of its replacement. Bad code endures when that cost goes up.
If there are some, I'm not really aware of them. Systems we create should be human-manageable. The thing I find interesting is that, even with decades of attempts at better practice, we still end up with complexity that makes our work difficult.
'Twitter, Reddit, and Conway's Law'
https://michaelfeathers.silvrback.com/social-media-architect...
It would indicate that the device is self-contained and has no connectivity.
https://scholar.harvard.edu/waldo/publications/note-distribu...
https://www.joelonsoftware.com/2002/11/11/the-law-of-leaky-a...
I don't think we have that same effect in software but I think there is an related one: when you don't have the protection of a static type system, you may become more careful.
Write a test if you don't feel confident that a piece of code does what you think it does. If you're not sure what it does now, there's little chance that you or anyone else will in the future, so write a test to understand it and to make that understanding explicit.
Use curiosity as a driver.
The GP points at the transition between the quick & dirty architecture and the architecture that handles Google-scale, but those aren't the only good stable points for a system.
[1] https://michaelfeathers.silvrback.com/the-myth-of-scaling
Just asking yourself what laws a function should adhere to as you are considering writing it function puts you in a different frame of mind and you can end up with simpler software.
I think array languages, or at least their operation set and idioms, will move into the mainstream in the same way that functional is, but it will take time. Sustainability for your business would be more an issue of hiring and retaining talent.
Reach out if you want to talk about this more: @mfeathers
For the past few years I've been telling people about the APL family of languages. The clincher for me was seeing the video of an APL version of Conway's Life mentioned in the submission. The impressive part wasn't its brevity, it was how they approached the problem.
In APL you have a 'rotate' operator that shifts data in a particular direction. If you have a vector and you rotate it once, every element moves to the next position and the last element then becomes the first.
The nice thing about APL is that most operations work on data regardless of its dimensionality. So, to do Conway's Life, you take your 2D matrix of cells and produce rotations of it in eight directions (N,NE,E,SE,S,SW,W,NW). You then take those rotated versions of the matrix along with the original and conceptually stack them. Then, for each grid point, you sum downward, producing a new matrix that contains the neighborhood count of the original matrix. From that you can create the next Life generation.
This sort of problem doesn't come up everyday, but the thing that I think is profound is that the existence of these operations allows us to think about problems in different, possibly simpler ways. They are untapped potential and they could be as well known as map and fold.
APL and its derived languages are hard to approach but there isn't much that keeps us from importing the data structures and operations in more approachable languages.
Ideal situation: tester doesn't find anything.
Automated testing is the process of writing code to understand your code. We already have to understand our code. Testing is being deliberate about that understanding and writing it down. The same design/testing thoughts that lead us to edge cases can lead us their elimination without testing at all. It's an integrated process, not something separate.
I agree. This idea doesn't receive enough attention. If you pick your constraints you can make a particular envelope of uses easy and ones you don't care about hard.
AWK's choice to be a per line processor, with optional sections for processing before all lines and after all lines is self-limiting but it defines a useful envelope of use.
A typical scenario is:
1) Product becomes too hard to change but has many existing customers
2) Product is off-shored, and costs of maintenance are under-estimated because it depends on a vast technical ecosystem
3) Alternative products are developed to replace revenue of the original
The original product can live in this moribund state for decades.
It would've been interesting to see this addressed. In some particularly bad cases, organizations atrophy and lose the ability to respond well.
It needs an xkcd graphic.