Hacker News new | ask | show | jobs
by manuelabeledo 1558 days ago
> But TDD works, you're the sinner for not using it right!

I often tell my colleagues that if technologies or methodologies are widely misunderstood, then practitioners aren’t to blame.

TDD might be great, but I have yet to see it widely succeed because its adoption is troublesome. It’s a bit like any of these newest products that promise to address everything consumers demand, only to fail miserably against the same old, leaving the few adopters asking themselves why commoners didn’t get it.

7 comments

I would agree… except that MOST programming technologies and processes are widely misunderstood, and it feels increasingly so.

Get 10 random senior programmers in a room, and see if they agree on matters of design, code structure, testing, frameworks, system architecture. I’ve been part of summits trying to do this several times over the decades, and the only agreement we wound up with was that “Layered abstractions are sometimes a good idea”.

There is a lot of duplication of effort in languages, frameworks, and tools driven by “I can’t be bothered to learn this new idea, I know better”, and a lot of misunderstanding of even first principles.

Something like TDD (and other XP practices like pairing) reminds me of diet/fitness /nutrition regimens that are notoriously difficult to comply with. This isn’t to say they don’t work: athletes and bodybuilders do exist, as do many successful TDD practitioners. It’s just human nature to avoid things that require mental change, or to be prone to self deception in their application.

> Get 10 random senior programmers in a room, and see if they agree on matters of design, code structure, testing, frameworks, system architecture.

I see this often when the problem is abstract. When the problem is concrete, I rarely see this come up in practice.

I routinely have 4-5 senior engineers in a room agree on architecture, design and methodology for a single, specific, project. To me, these abstract disagreements are a symptom of a generalization mismatch.

> Something like TDD (and other XP practices like pairing) reminds me of diet/fitness /nutrition regimens that are notoriously difficult to comply with.

But these regimens do work. It's just that they don't work for the reasons most people believe.

Take fasting. Most benefits of fasting in casual practitioners come from the obvious fact that they aren't consuming as much calories as they did before, so they lose weight. That doesn't mean fasting works in a different way from, say, just eating less.

Same goes for TDD. It may be beneficial because it forces a culture of testing and code coverage, but the root of such benefits may not be writing tests before code, yet that's what most people agree TDD is about.

I thought this was exactly the point of TDD and fasting but maybe I'm going to the wrong church.
Another reason why it's so hard to actually say "tdd does/doesn't work" is that everyone has their own idea what it is.

Its like everything in software engineering: everyone has an opinion, few have actually tested theirs with performant and stable production deployments

I think, additionally, it's domain specific.

There are problems where TDD is actually a decent approach. If you have solid requirements beforehand, and your problem does reduce to small bite sized units with trivial state, then it's amazing for producing code that doesn't surprise you when you run it.

There are problems where it really really really isn't. Things where there is ambiguity in the expected outcome. Language processing for example is fairly difficult to tackle with TDD. There is no simple state, there is no unambiguous expected outcome. Whether "jump" is a verb or a noun non-trivially depends on the context, and it may even ambiguous. The correctness of such code is a percentage value, not a boolean.

For context, when I debug the keyword extraction for my search engine crawler, I'm looking at test output that looks like this: <https://memex.marginalia.nu/pics/frog-text.png> (blue are individual keywords, red are potential n-grams).

Isn't the acronym, test driven development?

All that means to me is that when we start a project we think about what it means for an implementation to be correct and write a test. If we agree on the specification, the test, then a passing implementation means that we have implemented it correctly -- for that particular test.

One of the challenges of using unit tests for this kind of testing is, as you say, difficult with modelling continuous values.

It is also difficult because the "proof" is so small and trivial. You need thousands of examples to gain some confidence... and for even moderately complex software this can not be enough.

Unfortunately, the path to writing good tests and verifying software requires a bit of mathematical vocabulary and reasoning which many developers are too shy to learn or outright hostile towards ("I've never needed no stinking math, this is programming!").

My point is: as long as you're driving the development of your software using testing, I think you're practising TDD.

Unfortunately, it's hard to be put into a position where you can apply one, let alone multiple new approaches to software development on a team developing a large application for a long time (say at least 2 years). You'll have team churn, you'll have requirements churn, you'll have understanding of methodologies and practical realities change, etc.

So by "testing their (opinions)", I usually understand people to mean that they've been on a project where they've enjoyed working on something in a particular way (people always underestimate what someone is simply enjoying doing, I have no idea why). I understand that almost nobody is able to compare and contrast two significantly different approaches, let alone establish things like incident rates or cost of improvement and such resulting from application of those approaches (because there's no reference point).

What we do need is for all developers to contribute to setting up a foundation dedicated to establishing software development methodology quality, and then have that set up a dozen teams of 4-8 engineers working on a dozen longish problems (6-36 months) with different methodologies, and then aggregate and analyze results in 12 years. All the engineers would have market-rate salaries, so we'd all have to be chipping in monthly :D

I mean, just imagine where we'd be if we've done that in 2010? (probably at the same place, but just maybe not!)

Or TMTOWTDI.

Or there's hidden assumptions that differentiate between a Google solution and a coffee shop solution.

Performant... stable... both have ridiculously variable definitions based on who you talk to. That alone is probably enough to get your 10 Sr. developers to provide different solutions.

I don’t think the assumptions are hidden. There is plenty of literature with a reasonable discussion of the range of definitions of performance and scale. It’s that people aren’t even looking for them. It’s about “Team Red vs Team Blue”. Or whatever buzzword needs to be on your resume alongside leetcode for the next interview. NoSQL vs SQL, FP vs OOP. Can’t get my raise if I’m building coffee shop solutions!

The counter to TMTOWTDI is a set of principles and discipline, at least within a team or a project. Not to outright reject the alternatives, but to recognize the power of consistent behaviour and prioritization of tradeoffs, to try to counter the brand allegiances.

> I don’t think the assumptions are hidden.

And yet in the very article we're talking about, there's no explanation of what assumptions the author is operating within.

I'll even go so far to say that most technical articles omit the assumptions - because it's boring content and is less likely to engage the readers.

Most senior engineers I talk to would give you "conditional answers" on those, and I wouldn't be surprised at all.
> Get 10 random senior programmers in a room, and see if they agree on matters of design, code structure, testing, frameworks, system architecture

Programming consist of different schools of thought, similar to philosophy or economics, thus conflicting view points are not necessarily wrong per se, but they collide with your school of thought. Therefore there will always be some disagreement even between the most experienced programmers.

Now there are of course still things that a right or wrong on a factual level within programming, but because different schools also labels things as right or wrong it can be hard to distinguish what is grounded philosophical reasons and what is based on factual reasons.

In my experience, there is little disagreement with how to solve a problem as with the problem being solved.

I've found that within the high performing engineers, they tend to agree quite often with the solution once they agree upon the priorities of features and the problems being prevented.

Development practices are not difficult to comply with because you make them work for you, not the other way around.

The issue that I see in software engineering is the XOR approach. Top-down vs bottom up, abstraction vs implementation. This is the wrong thinking. One of the classic books on software architecture said paraphrased "The architecture drives the implementation and the implementation drives the architecture". A classic book on software development said paraphrased "You design for the implementation you need and implement for the design you want.

It's a yin and yang. But many software engineers completely fail at this. They get stuck at implementation or design. You need both at the same time. They're trying to represent a many dimensional problem one or more dimensions lower than required. They're flat-worlders trying to describe a cube or even a tesseract. Of course there's going to be misunderstandings and mistakes. Everyone has a difference view of the cube. They're technically talking about the same thing, yet fail spectacularly when the parts don't quire align when they come together. The problem is very simple in a higher dimension.

Where are the lines drawn?

Take Agile. It clearly outlines that you cannot have managers getting in the way. Yet, I don't know how many companies I've seen trying "Agile" without giving up their managers.

If you're not even willing to move past the first step, indeed it is doomed to failure. But surely you should recognize that when you decide to go down that road?

Removing the managers from the equation requires a team of developers who have a very business-oriented mindset. I expect a lot of developers don't have that, and may not even be capable of it. For any given business, chances are that does not describe your team. I think it is fair to say that Agile is not realistic in the vast majority of cases.

Is the fault Agile for being written for a narrow scope of situations or for practitioners trying to adopt it where it was not designed to fit? I would suggest the latter.

> Is the fault Agile for being written for a narrow scope of situations or for practitioners trying to adopt it where it was not designed to fit? I would suggest the latter.

I believe Agile is one of the main offenders here. You suggest that Agile is not "realistic" in most cases, and I agree with that, but Agile consultants and practitioners like to say that Agile is about taking what works for you, and adapting it to your needs.

I think Agile adoption by people who believe in this, is doomed. When Agile is seen as a set of nebulous guidelines from where you can pick and choose, it just doesn't work, and in turn, these experiences feed the idea that Agile doesn't work as a whole.

Agile with managers

- We have rearranged your sprints because of super duper important deadline for a very important customer.

- But we already begun this sprint!

- Yeah, but we are Agile.

It's like everything in programming. The 1% of the elite can use almost any methodology with great success, but the other 99% constantly fail to perform.

The problem solving aspect of programming is hard for most people. Nearly all of the high performers that I know are on the high functioning autism spectrum. They spearhead the hard technical problems, and set the stage for everyone else to tag along wit the busy work.

It takes all kinds to make a team, but we still need to recognize everyone's strengths and weaknesses.

And not every problem in programming is a technical problem. There are more issues in communication and understanding the problem being solved. Doesn't do much good to have a technically correct product that doesn't quite solve the problem.

What software engineering needs is a methodology in management to identify and properly utilize everyone to their unique abilities.

Like everything in programming, the cultural part is more difficult than the technical part. I've seen more than one a fellow coworker comment all my tests. If you don't create the correct culture, and there isn't management buy in, it won't work.
I believe that in medicine, if a treatment fail because the patient doesn't follow it correctly, it is considered a failure of the treatment (of course better education can be part of the solution).
I worked with a guy who has since transitioned to teaching Agile methodologies, and one day he was talking about his mentor, 'Jay' and the methodology they used within Jay's consulting practice.

Most of the successful projects, Jay brought in a team of people he had worked with before. So at some point you have to ask if it's the methodology that makes the project successful, or the people who make the methodology work.

If you have ever been a Lead, or even a viable candidate for one, you've had meetings with others to conspire to be successful within the bounds of whatever rules management won't budge on. How to make this number say what we want it to say. How to make that graph go in the right direction. In these cases we are camouflaging our personal methodologies to pass for someone else's. We are succeeding in spite of them, because if we told them what we were doing they might make us stop.

So when they look back at the project, all they see is the things we let them see. The opinion of the person who introduced a change is never the one you can trust. You should ask the people in the trenches what they think.

How many of the people who misunderstand the technology or methodology actually learned it from some kind of official or primary source, though?

Compare that to how many of us learned "OOP" or "TDD" or "FP" or "DDD" from a few blog posts.

Is it physicists' fault that I can "learn" that quantum mechanics says CERN opened up a wormhole and alternate timelines from a crystal salesperson on Facebook?

There are a number of tech fads that were unknowingly widely promoted as a panacea whose applicability is limited to particular specific circumstances.

Microservices is another.

TDD gets pushed especially hard (I think) because when it works well it works REALLY well and because it can be quite literally addictive - the red/green being like sounds on a slot machine that generate a hit of dopamine.

Thats a recipe for some passionate promotion.

In fairness to the original author, his heterodox form of TDD does widen its applicability beyond its traditional scope of complex, stateless algorithmic code with simple APIs to the more common integration code that involves databases, etc. that predominates in most commercial code bases.

But, what tech innovation DIDN’T start as something with limited applicability? The only way to know is to discuss the benefits and tradeoffs in something approaching social science.

But humans struggle with rigor, it’s much easier to brand and market something, or to buy in to brands. So “ideas” like microservices become brands. And they’re misunderstood and misapplied because people don’t read the copious literature that discusses the tradeoffs and variations. And they don’t practice it as a discipline with someone that has mastered the technique successfully: they do it blind.

Same goes for TDD or other XP practices that are often deride as cultish. being a discipline is even harder to adopt than a design philosophy like microservices. Disciplines are about consistent behaviour. To an outsider, it’s freaky. But calling it cultish as some do is like saying Karate or another martial art is a cult. From the outside it kind of looks like it, but discipline or kata (practice of form) is known to be a success multiplier for the sustained successful application of practices.

If you don’t have a dojo or a sensei, could you teach yourself such a set of martial arts to mastery? If not, why do we expect everyone to pick up TDD after reading a book?

TDD gets pushed because it creates great, easily trackable metrics one can gesture to as evidence that a) your code is good and b) that you're doing a good job and should be paid more.

It makes developers happy because it translates the somewhat arcane nature of the work into something easily digestible by management, and is a fig leaf for shoddy work.

It makes management happy because it goes nicely on a chart that can be shown to the director/customer/shareholders, and looks good at status meetings. It also gives them something to poke at and micromanage.

It makes the customer/shareholders happy because it provides a metric that their money is being spent _doing something_.

TDD may have started as a coding best practice, but it exists and endures - and will continue to exist and endure - because it's performative, and the performance has value to every layer of a business, even though it has nothing to do with actually making the product better at this point.