What you describe is - at least in my experience - a quite common emergent pattern of teams trying "to be Agile". It is open for debate if this is actually part of Agile itself or a common mis-implementation of it, is against the agile manifest/principles or an inherent consequence of it, and so on. Just from an empirical standpoint and just based on my own small sample set of experience (and the people I talk to), if a team is agile it seems to have a higher than average chance of running into this pattern. Let's just leave it at that and focus on your concrete example.
There are two separate aspects to what you describe:
- Missing common understanding/vision and therefore not being efficient
- How to measure success/progress and total cost
Going down the wrong path or running in circles
In my experience, the main reason for this to happen is that in an attempt to produce code quickly, teams actively push aside use cases or requirements they already know or could easily find out about. Think of it this way: 10-20 years ago, people tried to write giant specs and think of everything in advance and often failed. They either took too long or overlooked something. One of the learnings of the past is that in software development there are things that you cannot know and things change a lot, hence the idea of iterating quickly and producing some sensible output fast. Which is a very good principle. But today, we are at the other extreme: "I don't care about this because it's part of the next sprint" or "I don't file that bug, I deal with it when it comes up again". My advice would be:
- Gather all the high level use cases, requirements, dependencies and restrictions you can find. Put it in some wiki so all stakeholders and devs can see them. Add to them when something new comes up. Talk to your shareholders & users. Use this as a check list while developing to prevent implementing things that don't contribute to the final product or are workaround/hacks that solve one problem but cause three new ones.
- Formulate a high level concept. I'm not talking about designing interfaces or classes, but instead roughly sketch out the problem domain. What are the main elements, mechanism and interactions in the final solution? In your case, it should make it obvious when using the jquery-workaround helps as an intermediate step and when it only causes additional work.
- Validate your concept using the list you gathered. Are there any obvious problems in it? Does it make sense? Are there more efficient ways to achieve the same user value without causing long time tech debt?
Don't overdo it. You just need something so everyone in the team (including non-devs) has a common understanding what the best path to your MVP is. Everyone should agree that there are no obvious oversights and it could actually work. This in general helps prevent going down dead ends or having to redo the same thing multiple times. Agile can help you deal better with the unexpected, it is no argument to ignore what is known.
Be aware of the sunk-cost-fallacy: if you start with one architecture or database type, most people are hesitant to change it mid-project. So it's a good idea to invest some time in having an "educated best guess" before starting to implement stuff. Devs have a tendencies to want to write code quickly. But often having a couple of mocks, live prototypes, screenshots, wireframe, etc allows for even faster iteration than writing code. Just be aware that every line of code written or even unit tests make it harder to change your overall concept again.
Measuring Success
A completely separate aspect is how you measure progress. Let's say the goal of your project is to build a tower that is 1m high using things lying around. Building a house of cards can be a totally valid solution if for example time to market is more important than stability. If your goal is to build something that lasts, using Lego would have been better. The point is: what is considered a hack and what an elegant solution dependents entirely on how the project's success is measured.
Your example of the "loading" is pretty good. I had things like this in the past where everyone (including sales, PO, users) agreed it was annoying. But it had no impact on the success of the product and caused no long term debt. So we dropped it because there were more valuable things to do with the dev-resources.
My advice here is:
- Keep everything, even small bugs, as tickets in your ticket system. Make an active decision what is within the project scope and what not. Create milestones or otherwise filter your backlog so you always have a "complete" list of everything that still needs to be done.
- Have a strict order of importance and clear cut off point where the project could be considered a success. What level of stability / code quality / documentation does the final product actually need? Try to spend every day of work as best as possible by picking from the top. When working on one ticket, try to solve it completely without introducing new tickets (unless it makes sense to post-pone things due to lower priority). Every commit should bring you forwards towards your end goal, not sideways or backwards. But to stress it again: sometimes a hack that produces additional work later on can still be a net positive for the project!
- Use your PO/users to figure out the user value but also have your devs figure out the tech cost. Non-devs typically cannot judge what the true longterm cost (not just implementation cost!) is, so help them. Be aware of the boiling-frog problem: lots of little, irrelevant problems can over time bring a team to a hold. Try to quantify how efficient your team can work.
- Keep an eye on the overall goal/costs. Instead of thinking from sprint to sprint, rather keep a mindset of "can we as a team do everything needed until the end of the project". Sprints are just a way to break things down and have check-points.
- Instead of wanting to show something early, plot your course on the fastest path to a minimum viable product that can be given to the user. Still, your overall strategy should allow for verifiable results in between.
So when someone does something that does not fit into your final implementation goal, ideally don't consider the story done. If it is beneficial to close the story (e.g. to get feedback from customers), immediately open a new story/bug to address the short comings. Make it transparent that taking shortcuts does not reduce costs, it just hides or delays them!
The trick here is to argue with total cost of the project: if for example a PO pushes for taking shortcuts to make a deadline, quantify the amount of work that has to be done afterwards to consider the project done!
Also beware of criteria-based-optimisation: if your team is measured by the number of stories they can show at a sprint review, the best way to achieve a good "score" is to cut every story into ten tiny ones. If it is measured by the number of unit tests written, it will tend to write lots of unnecessary ones. Don't count stories, rather have a measure of how much of the needed user functionality works, how big the cost by tech debt to be solved within the project scope is, etc.
Summary
To boil it down: Going fast and minimal is a good approach. The problem is in interpreting "fast" and "minimal". One should always consider the long term cost (unless you have a project where this is irrelevant). Using a shortcut that only takes 1 day but produces tech debt of 1 month after the shipping date costs your company more than a solution that took 1 week. Immediately start writing tests seems fast, but not if your concept is flawed and they cement a wrong approach.
And keep in mind what "long term" means in your case: I know more than one company that went bust by trying to write great code and therefore shipped too late. A good architecture or clean code - from a company perspective - is only valuable if the cost to achieving it is less than the cost of not having it.
Hope that helps!