Building a life-critical System using Agile [closed] - unit-testing

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Looking at the general trend of comments in my question about Building an Aircraft using Agile, the biggest problem other than cost appears to be safety.
Do people feel that it is not possible to build a safe system (or prove it is safe) using agile? Doesn’t all the iterative testing mitigate this? Is it likely that a piece of software developed using agile will never be as reliable as counterparts such as waterfall?

Agile is a method of managing a project, not a method of testing or verifying the safety of a finished project.
A safety critical system would still need extensive testing after it is complete (functionality wise) to be absolutly sure it is actually up-to-task. I would expect that this sort of work would be given over to a separate team of testers who are specifically focussed on such testing.
Agile is good with soft requirements, where the traditional product lifecycle is long enough for the business goals to have changed, though in a safety-critical environment, I think that rapidly changing requirements or under-specified requirements would be A Very Bad Thing.
I don't buy the idea that using waterfall would in some way give the code some intrinsic order or stability - if the individual sprints are well managed, the code tested and reviewed, then the shorter cycle would produce code of equal quality, just in chunks.
Using Scrum gives you a heads-up earlier in the project timeline when things are getting problematic - it's not going to do anything but remove hiding places for poor performing managers / devs / whoever.
In short, it is possible to build any sort of system using Agile methods, just so long as you don't expect it to test what you have built. Thats for the testers.

There are a number of high-profile software failures that illuminate this issue. In particular, Ariane 5 Flight 501 and the Therac-25 are both examples of software failures that bring this problem into sharp relief. The Ariane 5 rocket veered off its flight path 37 seconds after launch due to an integer overflow in the guidance software. The accident cost $370 million in lost equipment, but there was no loss of life. The same cannot be said of the Therac-25, a medical machine that killed several people with lethal doses of radiation.
Could these problems have been prevented with a better software methodology? I'm not so sure. The management decisions that contributed to the failure of the Ariane 5 had little to do with the manner in which the software was constructed, and the Therac-25 investigation was hampered by the belief that it was not possible for the machine to fail.
Better testing methodologies could have helped. It's hard to believe that a good statically typed compiler would have failed to find the integer overflow. New testing methodologies like Pex, with its built-in theorem prover, have the capability to search for corner cases, and could have identified the sensor anomalies that existed in the Therac-25.
But no technique is reliable unless you have an uncompromising commitment to safety, from the very highest levels of management all the way down to the people who box the product for shipment.

The WHOLE point about safety critical systems that everyone seems to be missing here is that because of their potential to cause loss of life (sometimes on a large scale), they have to be proven to be correct. Often they require an operating certificate unless a licensing authority that is satisfied that the system's requirements have been accurately specified, (often using formal methods like Z and VDM), that the design is a reflection of those requirements (and can be proven to be such) and that the code is an accurate reflection of the design (again proven to be so).
More often than not, the option to test the product to provide such proof doesn't exist (OK guys let's go life with the nuclear reactor, Boeing 777, Therac 25 - whatever and see where the bugs are). Safety critical systems (especially those categorised at S.I.L 3 and above) need thorough and comprehensive documentation which is totally at odds with the Agile manifesto in all respects as far as I can see. Programmers of safety critical systems are not even allowed to make changes to the relesed software without requesting a new revaluation of the software from the licensing authority and rightly so, given the rigour that goes into proving the correctness of the first version and the catestrophic implications for a screw up.

Agile is a dynamic development model - You use it when requirements of your application are to be changed fast and unforeseen. Also if the number of your developers are still countable.
You do NOT use it just because it is modern/in/hip/cool.
Sure you can find errors with unit tests, but they never prove their absence. Changing/Adding requirements of the application during development greatly involves adding hidden errors.
For exactly planned applications which is typical for safety critical applications you want to use more static development models like waterfall or v-model.

Most safety critical or mission critical systems can benefit from a more standard development structure such as the waterfall model and formal code reviews. Such methods help maintain a more structured code base. Great Book about software construction - especially if the project has already begun using an Agile process - Code Complete 2 ed.

Related

How to gracefully integrate unit testing where none is present? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I have been tasked with developing a document for internal testing standards and procedures in our company. I've been doing plenty of research and found some good articles, but I always like to reach out to the community for input on here.
That being said, my question is this: How do you take a company that has a very large legacy code base that is barely testable, if at all testable, and try to test what you can efficiently? Do you have any tips on how to create some useful automated test cases for tightly coupled code?
All of our new code is being written to be as loosely coupled as possible, and we're all pretty proud of the direction we're going with new development. For the record, we're a Microsoft shop transitioning from VB to C# ASP.NET development.
There are actually two aspects to this question: technical, and political.
The technical approach is quite well defined in Michael Feathers' book Working Effectively With Legacy Code. Since you can't test the whole blob of code at once, you hack it apart along imaginary non-architectural "seams". These would be logical chokepoints in the code, where a block of functionality seems like it is somewhat isolated from the rest of the code base. This isn't necessarily the "best" architectural place to split it, it's all about selecting an isolated block of logic that can be tested on its own. Split it into two modules at this point: the bulk of the code, and your isolated functions. Now, add automated testing at that point to exercise the isolated functions. This will prove that any changes you make to the logic won't have adverse effects on the bulk of the code.
Now you can go to town and refactor the isolated logic following the SOLID OO design principles, the DRY principle, etc. Martin Fowler's Refactoring book is an excellent reference here. As you refactor, add unit tests to the newly refactored classes and methods. Try to stay "behind the line" you drew with the split you created; this will help prevent compatibility issues.
What you want to end up with is a well-structured set of fully unit tested logic that follows best OO design; this will attach to a temporary compatibility layer that hooks it up to the seam you cut earlier. Repeat this process for other isolated sections of logic. Then, you should be able to start joining them, and discarding the temporary layers. Finally, you'll end up with a beautiful codebase.
Note in advance that this will take a long, long time. And thus enters the politics. Even if you convince your manager that improving the code base will enable you to make changes better/cheaper/faster, that viewpoint probably will not be shared by the executives above them. What the executives see is that time spent refactoring code is time not spent on adding requested features. And they're not wrong: what you and I may consider to be necessary maintenance is not where they want to spend their limited budgets. In their minds, today's code works just fine even if it's expensive to maintain. In other words, they're thinking "if it ain't broke, don't fix it."
You'll need to present to them a plan to get to a refactored code base. This will include the approach, the steps involved, the big chunks of work you see, and an estimated time line. Its also good to present alternatives here: would you be better served by a full rewrite? Should you change languages? Should you move it to a service oriented architecture? Should you move it into the cloud, and sell it as a hosted service? All these are questions they should be considering at the top, even if they aren't thinking about them today.
If you do finally get them to agree, waste no time in upgrading your tools and setting up a modern development chain that includes practices such as peer code reviews and automated unit test execution, packaging, and deployment to QA.
Having personally barked up this tree for 11 years, I can only assure you it's incredibly not easy. It requires a change all the way at the top of the tech ladder in your organization: CIO, CTO, SVP of Development, or whoever. You also have to convince your technical peers: you may have people who have a long history with the old product and who don't really want to change it. They may even see your complaining about its current state as a personal attack on their skills as a coder, and may look to sabotage or sandbag your efforts.
I sincerely wish you nothing but good luck on your venture!

Is Scrum possible without test driven development? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 5 years ago.
Improve this question
I have now witnessed two companies move to agile development with Scrum.
In both cases the standard of coding was good enough when each part of the application was only being worked on by one or two developers with the developers spending a reasonable amount of time working on one part of the application before moving to the next task. The defect rates were also reasonable.
However with Scrum the developers are expected:
to all be able to work on all the bits of the application.
to only work on one area of the application for a few days at most before moving to the next area
to mostly work on code they did not write
Code qualities became an issue in both of the Scrum projects.
So is there a way to do Scrum that does not lead to these problems, without first getting all the developers to do test driven development?
Have you seen Scrum work well on a large project without test driven development? (If so how?)
I'd like to expand on what Dan said.
It's a very common misconception that Scrum / Agile dictates software engineering principles. This is a fallacy for many reasons. As Dan mentioned, Scrum is a software management process, NOT a software engineering process. That being said, very often you will see many engineering principles associated with Scrum; methodologies such as TDD, XP, etc tend to complement the management methodology that Scrum promotes, but are not required.
The reason that CI, TDD, and other engineering practices are so often found hand-in-hand with Scrum is that in general, many are good practices to follow no matter what management methodology is used.
I'd like to address a couple other fallacies in your OP:
However with Scrum the developers are expected:
* to all be able to work on all the bits of the application.
* to only work on one area of the application for a few days at most before
moving to the next area
* to mostly work on code they did not write
As mentioned above, Scrum doesn't dictate what type or kind of work a developer works on. The developers themselves decide on what work to commit themselves to; if a database-heavy dev wants to only work on the DAL and associated stories, there's no reason that they cannot.
Again, Scrum doesn't dictate anything about how to build the application, so your second point is moot (see point 1).
This is a fallacy, since there is nothing that says a developer should only work on code that isn't theirs, or anything about how a developer should develop. If a developer on a Scrum team finds his/herself only working on others' code, that would be coincidental, not because of the scrum process itself.
See this question/answer for more information on the qualities generally expected in a developer working Scrum.
Yes, Scrum describes the software management approach. The program and project management paradigm should not dictate whether or not you use test driven development.
TDD is a software development practice or technique and although it works well with Scrum I don't think it will make or break your success with the practice.
I have personally seen Scrum work well on medium sized projects without a test driven approach to development. That is not to say we didn't write automated tests, they just were not always written first.
Regarless of the use of Scrum, what you were seeing was a change from a code ownership approach to a communal code approach. In order for that to work, there has to be a process change which supports it. One such possibility is TDD. There are others (Automated unit testing even if doesn't drive design coupled with Code Reviews, strong design communication, greater design up front, not developing on code without first pairing with the original author on the code, and more I'm sure you could think of).
Communal approaches work in smaller communities (in large ones it can degenerate into a tragedy of the commons) with a high sense of cohesion between the members.
We do Scrum at work, but we don't practice TDD. Nothing in the Scrum "guidelines" tells you that you have to use TDD. In fact, most agile practices are merely a recommendation insofar that they have proven to work well in agile environments (or even non-agile ones) without them being a must if you want to implement Scrum.
We do write lots and lots of unit and integration tests to avoid extensive manual testing and ensure that later changes in the code doesn't lead to any unpredicted side effects. But that's not TDD. It's mostly a sensible approach to ensure good code and software quality.
Please note that not implementing TDD was not an "active" decision, it just happened. We are encouraged to "write tests first", e.g. when fixing a bug, so it's kind of a voluntary situation-driven not-obligatory way of getting a feeling for TDD by applying it on a regular basis, but it is not mandatory.
Like others said: Scrum is a framework which can hold whatever practices you want to enforce in your development team. Some agile practices come naturally, because they generally make sense, but which ones you want to use and which ones you don't want is up to you.
Yes, Scrum is entirely possible and in most cases implemented without utilizing a TDD approach.
However, the flexibility that TDD provides is certainly something that a Scrum methodology can benefit from.
The main project I work on uses a Scrum approach but the embedded nature of our project makes test-driven development (the way that most people do it) impractical.
I think the problem you encountered was that the expectations of the programmers changed, not that the management process went to a Scrum-style system. If programmers are constantly being shuffled around to parts of the code they are not familiar with, investigate the process behind how tasks are being delegated relative to the old method. Are tasks being assigned to the developer who knows that area the best or are they going to the developer with the shortest to-do list? Is there a long backlog of to-do items for one part of the code and a scarcity of to-do items for another part? If you want to keep developers focused on the areas they excel in, then project management will want to adjust sprint lengths and task priorities to make sure that the workload can be distributed as desired and still be feasible given the time constraints of the sprint.
The Scrum framework is pretty small, it defines a few meetings, ideal lengths of iteration, responsibilities of product owner, scrum master... and maybe a bit more.
However, once we have started our iteration there is nothing in Scrum that dictates how and when a developer(s) should develop something. There is only the committment it will be 'done' by the end of the sprint.
Scrum is about the team committing to produce results, and the team being empowered to decide how to do so. If that means 1 dev per user story, great. If that means 3 devs per user story thats fine also. Whatever way the scrum team believe to be the best way to do the job is what should happen.
To answer the question, yes Scrum is possible without test driven development.
TDD is a worthwhile/recommended practice but the results will vary depending on team/context. For example was TDD in place at the start of a project or are you trying to inject the methodology in at a later date.
There's some confusion about Scrum here.
Scrum per se doesn't tell you how/when to do technical things like TDD (that's a forever moving target). Scrum tells you how/when to manage the people things that happen on a project. It is a overall project management technique, not a construction management technique.
If your manager wishes to do the three things listed above during your sprints, that's fine, but that isn't part of the framework of Scrum. Those are for construction management, which isn't Scrum. It may be used in your Scrum-framework-bounded project, but it isn't in the official Scrum framework.
I think it's easy to be confused about this, though. Agile techniques like Scrum are usually evangelized by people on the 'net who are all about pushing buzzwords and 'happy shiny' things, and as such don't always understand/communicate well. At least, that's how Agile techniques were introduced to me, by an Agile apologist. It took me a good 6 months before I got past the hype / confusing terminology and figured out what they were talking about.
While there are parts I agree to above, I truly believe that you cannot deliver small increments of Code (Scrum for software) without Testing period.
How do you know your sprint didn't break the last 4? How can you guarantee deliverables if you don't know that you didn't break anything in the past.
While I do agree SCRUM is a management process and that TDD is a software process. You must have some way to be able to verify that you did not move backwards.
SCRUM teaches you that daily deliverables and always moving forward at the expense of speed.
When someone says I want to do CI or Agile or Scrum, to me this automatically means there needs to be unit testing (not integration testing as mentioned above) but rather each individual moving part has it's own unit tested.
If you do an integration test you are not testing each individual part in a self contained way. Therefore all you prove is that the method called in one flow works rather than each possible branch you would see in the MSIL

Reducing defect injection rates in large software development projects

In most software projects, defects originate from requirements, design, coding and defect corrections. From my experience the majority of defects originate from the coding phase.
I am interested in finding out what practical approaches software developers use to reduce defect injection rates.
I have seen the following appraoches used with varying levels of success and associated cost
code inspections
unit tests
static code analysis tools
use of programming style
peer programming
In my experience it has been the fault of the process, not developers, that permit defects. See They Write the Right Stuff on how the process affects bugs.
Competitive Testing
Software developers should aspire to prevent testers from finding issues with the software they have written. Testers should be rewarded (does not have to be financial) for finding issues with software.
Sign Off
Put a person in charge of the software who has a vested interest in making sure the software is devoid of issues. The software is not shipped until that person is satisfied.
Requirements
Avoid changing requirements. Get time estimates from developers for how long it will take to implement the requirements. If the time does not match the required delivery schedule, do not hire more developers. Instead, eliminate some features.
Task Switching
Allow developers to complete the task they are working on before assigning them to another. After coming back to a new task, much time is spent getting familiar with where the task was abandoned and what remaining items are required to complete the it. Along the way, certain technical details can be missed.
Metrics
Gather as many possible metrics you can. Lines of code per method, per class, dependency relationships, and others.
Standards
Ensure everyone is adhering to corporate standards, including:
Source code formatting. This can be automated, and is not a discussion.
Naming conventions (variables, database entities, URLs, and such). Use tools when possible, and weekly code reviews to enforce.
Code must compile without warnings. Note and review all exceptions.
Consistent (re)use of APIs, both internally and externally developed.
Independent Review
Hire a third-party to perform code reviews.
Competent Programmers
Hire the best programmers you can afford. Let go of the programmers who shirk corporate standards.
Disseminate Information
Hold review sessions where developers can share (with the entire team) their latest changes to the framework(s). Allow them freedom to deprecate old portions of the code in favour of superior methods.
Task Tracking
Have developers log how long (within brackets of 15 minutes) each task has taken them. This is not to be used to measure performance, and must be stressed that it has no relation to review or salary. It is simply a measure of how long it takes certain technical tasks to be implemented. From there you can see, generally, how much time is being spent on different aspects of the system. This will allow you to change focus, if necessary.
Evaluate the Process
If many issues are still finding their way into the software, consider reevaluating the process with which the software is being developed. Metrics will help pinpoint the areas that need to be addressed.
First, bugs injected at requirements time are far, far more costly than coding bugs. A zero-value requirement, correctly implemented is a piece of zero-value, unused (or unusable) functionality.
Two things reduce the incidence of bugs
Agility. You are less likely to inject bugs at every step (requirements, design, etc.) if you aren't doing as much in each step. If you try to write all the requirements, you will make terrible mistakes. If you try to write requirements for the next sprint, odds are better that you will get those few requirements correct.
TDD. You are less likely to struggle with bad requirements or bad design if you have to write a test first. If you can't figure out what you're testing, you have a requirements bug. Stop coding. Step away from the keyboard.
If you can't figure out how to test it, you have a design bug. Again, stop coding. Fix the design so it's testable. Then move forward.
I think the main problem of injection rates can become from a lot of sources, and it vary from environment to environment.
You can use a lot of best practices like TDD, DDD, pair programming, continuous integration, etc. But you will never be free from bugs, because what creates bugs are human people, and not exactly the processes.
But IMO, using a bug tracker tool could bring you hints of which problem is more recurrent. From there, you can start attacking your main problem.
The majority of defects may occur during coding, but the impact of coding defects is generally much lower than the impact of errors made during the process of understanding requirements and while developing a resilient architecture. Thus the use of short executable-producing iterations focused on
identifying and correcting ambiguous, imprecise, or just plain incorrect requirements
exposing a suboptimal and/or brittle architecture
can save enormous amounts of time and collective stomach lining in a project of significant scope.
Unit testing, scenario testing, and static analysis tools can detect defects after they are created, but to reduce the number of defects created in the first place, reduce the number of interruptions that developers must endure:
reduce, eliminate, and/or consolidate meetings
provide an interrupt-free working environment
allow developers to correct their defects when they find them (while the responsible code is still fresh in their mind) rather than defer them to a later time when context must be re-established
Step 1 - Understand where your defects are being injected.
Use a technique such as Orthogonal Defect Classification (ODC) to measure when in the software lifecycle defects are injected and when they are detected. Once you know when the defects are injected and have identified when they were discovered you can start to understand the gaps in your process with respect to defect injection and removal.
Step 2 - Develop defect "filters" and adapt your process
Once you know when defects are being injected you can devise strategies to prevent them from entering the system. Different strategies are effective at different points in the software lifecycle. For example, static analysis tools don't help with defects that originated in the requirements, instead you should be looking into some kind of peer review or inspection, maybe even changing the way requirements are specified so you use automated analysis or achieve a more meaning sign-off, etc.
Generally I use a combination of inspection, static analysis, and testing (many different kinds) to filter as many bugs as I can, as soon after they are injected as I am able.
In addition:
Project knowledge base. It says how we do activity X (like 'form validation') in this project. This allows unification and re-use of tested solution, preventing bugs injected when re-inventing-the-wheel.
Production bug monitoring. When a production bug occurs it is investigated. Why this bug was not caught? How we can ensure that this won't happen again? Then we change the process accordingly.

Is it legally negligent to not use unit testing [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
Is anyone aware of any legal precedents where the lack of unit testing in an application has lost someone a case
Or where someone has not been deemed negligent despite a lack of unit testing in an application.
Is there any highly regarded alternative to unit-testing that enables programmers to objectively demonstrate a committment to software quality.
For example in medicine you can use in your defence that your approach is one that is regarded as acceptable by a substantial and well regarded group of other doctors.
Legal is between you and whoever will pay for your software
If the contract said that you will do unit testing and you don't, then you're liable. It depends on every software and every agreement you make. When I buy Windows for critical software applications (laugh, laugh, it DOES happen), no one makes sure they unit tested everything
Unit testing is only a (very valid) alternative to test your code, it can't and could not be a legal requirement.
For example, you could prove some properties of a piece of code using a denotational semantic and some techniques that found their justification on well-founded relations, complete partial orders and fixed-point theorems.
A lawyer could probably find out for you, but it would probably be expensive.
In general, there's no liability in software. How good or bad a thing this is is debatable, but I haven't found a piece of software yet that doesn't disclaim liability. (There was a case where a tax preparation program several years ago had a problem, and the company actually recompensed people to some extent. I know of no other exceptions.)
Liability would normally only come about in embedded software, since a manufacturer is frequently liable for the behavior of a device, and the software is part of the device. In that case, demonstrating that sound software engineering practices were used might be useful, but I would be astonished to learn that failing to use unit tests would be considered negligence. (There is also, at least in the US, a concept of "strict liability", which means somebody's completely to blame, no excuses possible. It's been applied to navigational maps, but if you want to know for what else you need to consult a lawyer or do your own research.)
So, what I'm saying is that I don't know of any cases, it sounds dubious to me, I am not a lawyer, and this is not legal advice.
Unit testing, in a formal sense, is a relatively new concept in software (I'd guess less than 10 years old). Prior to that, some components and modules were tested, but it was more important that the overall system be tested.
Generally, the law lags behind contemporary practices by quite awhile. It takes a long time for laws, codes, and cases to establish a precedent. It would be very surprising to me if there is any consensus in law about a relatively new approach like unit testing.
User testing can be illegal in some cases (stackoverflow.com: what-legal-issues-surround-unit-testing-database-code-closed), because you can't allowed to do some things with personal data, for example in a database you wanted to include in your test.
In defense of a negligence lawsuit, an accused programmer might use extensive unit testing in his defense. If a contract specified unit testing, but none was conducted, then there would be cause for breach of contract.
Unit testing is not enough to reveal every possible fault, and there is not an ISO standard for it yet. A naive court might be convinced that it indicated neglect, but it is surely not founded upon a great body of legal precedent.
Unit testing is a good idea in general, but the field of software engineering has a long way to go until it's a standard practice that people can be sued for not doing. There are many cases where unit tests are simply not appropriate. Unless it's explicitly mentioned in a contract, there shouldn't be an expectation that unit testing will be used for a product.
Unless you are IBM you. Should not be in a position to gurantee your code is defect free.as strange as it sounds this is the clients responsibility.
I have worked on softwares which are critical applications that are installed only when the seller gives a buyer a complete list of testing done on the software and undersigned physically by the testers and the QA. this involves even if there is small unit which undergoes minor modification.
Mate, if your a real developer getting paid you should already know why unit tests are valuable in maintaning quality and other merits. I certainly might not sue you but i would fire you. Asking such a question demonstrates that you are a cowboy without a professional attitude in deliverying a quality product.

YAGNI - The Agile practice that must not be named? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
As I've increasingly absorbed Agile thinking into the way I work, yagni ("you aren't going to need it") seems to become more and more important. It seems to me to be one of the most effective rules for filtering out misguided priorities and deciding what not to work on next.
Yet yagni seems to be a concept that is barely whispered about here at SO. I ran the obligatory search, and it only shows up in one question title - and then in a secondary role.
Why is this? Am I overestimating its importance?
Disclaimer. To preempt the responses I'm sure I'll get in objection, let me emphasize that yagni is the opposite of quick-and-dirty. It encourages you to focus your precious time and effort on getting the parts you DO need right.
Here are some off-the-top ongoing questions one might ask.
Are my Unit Tests selected based on user requirements, or framework structure?
Am I installing (and testing and maintaining) Unit Tests that are only there because they fall out of the framework?
How much of the code generated by my framework have I never looked at (but still might bite me one day, even though yagni)?
How much time am I spending working on my tools rather than the user's problem?
When pair-programming, the observer's role value often lies in "yagni".
Do you use a CRUD tool? Does it allow (nay, encourage) you to use it as an _RU_ tool, or a C__D tool, or are you creating four pieces of code (plus four unit tests) when you only need one or two?
TDD has subsumed YAGNI in a way. If you do TDD properly, that is, only write those tests that result in required functionality, then develop the simplest code to pass the test, then you are following the YAGNI principle by default. In my experience, it is only when I get outside the TDD box and start writing code before tests, tests for things that I don't really need, or code that is more than the simplest possible way to pass the test that I violate YAGNI.
In my experience the latter is my most common faux pas when doing TDD -- I tend to jump ahead and start writing code to pass the next test. That often results in me compromising the remaining tests by having a preconceived idea based on my code rather than the requirements of what needs to be tested.
YMMV.
Yagni and KISS (keep it simple, stupid) are essentially the same principle. Unfortunately, I see KISS mentioned about as often as I see "yagni".
In my part of the wilderness, the most common cause of project delays and failures is poor execution of unnecessary components, so I agree with your basic sentiment.
The freedom to change drives YAGNI. In a waterfall project, the mantra is control scope. Scope is controlled by establishing a contract with the customer. Consequently, the customer stuffs all they can think of in the scope document knowing that changes to scope will be difficult once the contract has been signed. As a result, you end up with applications that has a laundry list of features, not a set of features that have value.
With an agile project, the product owner builds a prioritized product backlog. The development team builds features based on priority i.e., value. As a result, the most important stuff get built first. You end up with an application that has features that are valued by the users. The stuff that is not important falls off the list or doesn't get done. That is YAGNI.
While YAGNI is not a practice, it is a result of the prioritized backlog list. The business partner values the flexibility afforded the business given that they can change and reprioritized the product backlog from iteration to iteration. It is enough to explain that YAGNI is the benefit gained when we readily accept change, even late in the process.
The problem I find is that people tend to bucket even writing factories, using DI containers (unless you've already have that in your codebase) under YAGNI. I agree with JB King there. For many people I've worked with YAGNI seems to be the license to cut corners / to write sloppy code.
For example, I was writing a PinPad API for abstracting multiple models/manufacturers' PINPad. I found unless I've the overall structure, I can't write even my Unit Tests. May be I'm not a very seasoned practioner of TDD. I'm sure there'll be differing opinions on whether what I did is YAGNI or not.
I have seen a lot of posts on SO referencing premature optimization which is a form of yagni, or at least ydniy (you don't need it yet).
I don't see YAGNI as the opposite of quick-and-dirty, really. It is doing just what is needed and no more and not planning like the software someone writes has to last 50 years. It may come rarely because there aren't really that many questions to ask around it, at least to my mind. Similar to the "don't repeat yourself" and "keep it simple, stupid" rules that become common but aren't necessarily dissected and analyzed in 101 ways. Some things are simple enough that it is usually gotten soon after doing a little practice. Some things get developed behind the scenes and if you turn around and look you may notice them may be another way to state things.