I have also noticed that in Agile teams refactoring is generally not rewarded and sometimes is even discouraged. Instead it is a voluntary effort taken at the developer's expense and risk, which is perhaps the greatest crime of Agile.
I have also noticed that in Agile teams refactoring is generally not rewarded and sometimes is even discouraged. Instead it is a voluntary effort taken at the developer's expense and risk, which is perhaps the greatest crime of Agile.
As a long time Agilist, the spread of Fake Agile is a sad thing to see.
Constant refactoring is a core Agile practice! https://martinfowler.com/bliki/OpportunisticRefactoring.html
When I worked closer to production the people at the workshops also cleaned and repaired their equipment every evening, crunch time or not. They didn’t just let their machines die long term because it may buy some time in the short term to skip maintenance.
Better to just incorporate refactoring into the estimate for any given coding task and do it without explicit permission. Unless of course you're in a culture that is willing to straight up miss a deadline in order to get refactoring finished.
It should be as implicit as attending planning meetings. For some reasons PMs usually have no problem forcing people to sit through meetings but they have a problem with spending the same amount of time refactoring .
I like including refactoring in tickets, but if the refactor is consequent it's not going to work. It's not so often thankfully, I usually manage to convince the PO of the value of it, then try to not budge once it's decided
Occasional there is a bigger refactoring project, but that's my normal day.
"That wasn't true Agile" is starting to sound about as credible as "That wasn't true Communism."
Best methodology: Self-organizing teams of experienced, expert engineers. Let them develop whatever process works best for the individual team and project.
That requires two things:
1. Hiring the right people.
2. Trusting them.
Most companies aren't willing to do this, so... we get a semi-unstructured form of micro-management hell which goes by the name "Agile." Regardless of whatever that term originally meant, this is what it means now.The difference is that many people have worked on highly functional "real agile" teams and can tell the tale.
> Best methodology: Self-organizing teams of experienced, expert engineers.
Minor quibble: While that is of course the best scenario, it can also work quite well with a few experts guiding the less experienced. Pair programming works wonders here.
If your team is all inexperienced newbs, I don't know what can save your project :)
> Regardless of whatever that term originally meant, this is what it means now.
Perhaps. I have no interest in debating word definitions though.
Sure, but is it really the "agility" or the people making the difference?
The highly functional teams I've worked on either ignored or satirized the elements of Agile development (e.g. the "story" format, story points, any sincere effort at estimation poker) to get out of those discussions as quickly as possible. This probably bears some similarity to how the original "Agile" developers dealt with the preceding methodologies.
“Build projects around motivated individuals. Give them the environment and support they need, and trust them to get the job done.”
“At regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly.”
So based on your description those teams were Agile in the sense meant by the manifesto.
The great Agile teams I was on had really good people on them. So, sure, they might have done great work in other environments.
Then again, this was the methodology they chose.
It also sounds like the teams you describe picked their own way of developing, which, in a Big Picture sense, is all the Agile Manifesto says: Let the team control their own work, and get out of the way.
Which, in a lawyerly and annoying, but still kinda true way, makes that team agile too :)
That’s what “Agile” is when you read the Agile Manifesto.
It seems every reasonable methodology quickly gets perverted by leadership to a top down, dogmatic dictatorship caricature of itself. Happened to OOP, Agile, will probably happen to FP. You could argue that what Lenin and friends did in Russia was also not what Marx had in mind.
But we have story points, epics, scrums, retros etc. Agile is very much more than that.
Most “no true agile” posts are really “no true scrum” because the issue is firmly in process and methodology rather than underlying principles.
In fact I’d say Scrum itself whilst designed to meet the principles doesn’t actually do so in practice.
Scrum as a base methodology isn’t too bad either but as always management prefers precise plans and a lot of Agile consultants are happy to feed that. Saying “let people make up whatever process they want” is actually quite profound because it often goes complete against what management wants.
If this is clear and understood, congratulations, you basically understand the gist of the French historian Michel Foucault's criticism of modernity (it supposes origins and progress when no such thing actually exists, so how do we talk about politics, history, ethics?), a criticism which would go on to inform all of contemporary Left politics, including contemporary progressivism and identity politics.
> Although there are places for some scheduled refactoring efforts, I prefer to encourage refactoring as an opportunistic activity, done whenever and wherever code needs to cleaned up - by whoever.
That is how I personally view refactoring as well. Its like a necessary sanitation ritual to keep things tidy like doing the laundry or the dishes but far more rewarding knowing that the change is more than mere maintenance, an improvement that simplifies things. Refactoring shouldn't require a scheduled event, but its the quantity of scheduled events that is visible and reinforced by the system.
1. Story points are only intended as a prognosis tool. If we produce 14p/week on average, we'll probably work through this 80p block in 5-7 weeks.
That's it.
When you start using it to evaluate teams or individuals, Goodhart's law sets in, and it all turns to garbage.
2. The reason you don't count refactoring or bug fixes as points is that they don't add user value. If you spend all your time fixing bugs you created earlier, you are not being productive to the customer. It's easy to get caught up in polishing your toys instead of delivering things the customer is paying for.
Though what's often unstated/forgotten ignored, is that refactoring and leaving the code in at least as good a shape as you found it, is an integral part of what calling a story "done" should mean.
This is the common pitfall with rewriting. It does not account for the existing software being tested in production for years. There often are subtle behaviors/bugs, that users by now rely on.
"Huh the behavior of this system is a little eccentric, but if I insert my code in just the right place, I can get it to do what I need!" This is how legacy systems get built.
Instead you have to ask, "How can I describe what this system does in one or two sentences?"
"How can I describe how it does it in a short paragraph?"
The first explanation should make it clear why you're building the new functionality into or on top of the system. The second explanation should make it clear how the system supports the new functionality and why it works. These two explanations form a team's shared understanding of the system. If you build a new system that conforms to this understanding, porting is straightforward, even if you don't replicate all the details.
Invariably, though, there are developers who are too lazy to ask how a system works, and instead crawl through the code sticking their new feature in likely-seeming places and leaving it in the first place where it seems to work, regardless of whether the reason it works is related to the shared understanding of the system. Because everybody else must keep this new feature working, there can be no understanding of the system separate from the system itself: there is just a mass of equally significant details. The intentional developers are reduced to the level of the random developers. There is no such thing as a rewrite of a system like this. All you can do is replicate it nut by nut, screw by screw, and then it still doesn't work because you didn't match the spacing of the screw threads.
The corollary to this is that if you build a complicated enough system, with an abundance of distinct places to plug in code, the random developers will always find a place to stick their code and will always be happy and "productive." This is the way to achieve architectural immortality inside a company: create something so complex that it can't be understood but solves every problem if you look hard enough.
Now legacy systems don't cooperate, well I guess they can just rewrite their APIs too because "software entropy".
If I can do it by putting a COM wrapper on top of 20 year old PowerBuilder code and then interact with it with C#, I can’t imagine a case where this can’t be done.
The services were baked into the model which made it easy to write in the first place but very hard to refactor. The code would load a "hollow" entity and then as the entity was interacted with: automagically over the wire the data would be lazy loaded. If you applied an SQL trace you might see over 300 separate SQL commands executed just to load a page that visually represented the entity.
This resulted in some dire performance outcomes, a simple for loop over a given collection on the entity could result in N round trips and sometimes even N*N depending on the data modelling in the back end for given types of data within a collection or association.
A primary issue of this system is that lots of client code had been written that didn't express its intent. There were about eight relatively complex clients of this software and nowhere in that code base did the client ask for the data it wanted upfront in a way that would allow someone to refactor it without rewriting every single one of those eight clients.
Now yes, you could refactor this "architecture-less" sub-system by replacing it with another "architecture-less" sub-system that was "better", but sadly you're left with the same problem: the clients will never tell you what data they need for a use-case they will just assume it will appear when its accessed. To add in those "data demands" you're performing huge shotgun changes across the entire code-base which are always too expensive to justify.
One particularly egregious example was a WinForm loading an entity and then stuffing it into the .Tag of a control where a handler would cast it back out later and access it again in a lazy-loading kind of way.
Your only hope in that case is some sort of static code analysis to attempt to reverse engineer the client's data demands but that's probably approaching as expensive as any of the changes.
I've actually done this on purpose, by getting a v0 API into production quickly (1 week), then getting a v1 with all the bells and whistles out with sufficient time. It completely replaces the the v0 microservice which is a separate deployment.
The first version provided a specific implementation of the functionality for a single, small user population. The full version scales to millions of users, globally. It is still small enough that we could rewrite it, if we had to. The infrastructure is actually harder to produce (as code) than the API functions themselves.
CD pipelines, extensive unit tests, automated smoke tests, automatically configured health monitoring... all of these things make it possible to replace a service with a different implementation that conforms.
It's a hard discipline to get to, but once you're there, it is often more economical to rewrite to move on. I guess that's not the case for the usual kinds of projects. We had to spend a year as an organization to get to the point where this was true. It's usually not worth the cost for small teams to do this.
That’s all true in theory, but how many organizations have badly written code that needs to be refactored and good dev ops practices and/or unit test coverage?
And that still goes back to my point about using the strangler pattern. You put a facade on top of the “legacy code”, write integration tests that capture existing functionality and you slowly start refactoring the code or replace entire subsystems as necessary.
As far as v0 versus v1. I did just the opposite. My microservice was written in Node/Express. It was our company’s first Node app, we were a Windows/.Net/IIS shop.
I could easily get buy in for Node because everyone was expected to know JS. But I would never have gotten buy in to set up a Linux server and I didn’t want to run Node on Windows.
I deployed the API on AWS lambda even though I knew it wouldn’t be good enough for phase 2 - 6MB request/response and the “warmup time”. I also didn’t know anything about Docker it Fargate (AWS Serverless Docker).
We got the first version in, I spent some time getting up to speed on Docker, Fargate, and a deployment strategy and rearchitected the entire back end hosting and deployment to use Docker and Fargate.
The unit of reuse in this architecture tends to be the entire API, or libraries published as open source. If there is generic code that is suitable for a library, it is also suitable for contribution. If there is a core business function that should be reused, it is a microservice with an API and gets shared and consumed that way.
Our hard rule for refactoring or enhancing services is if it is a breaking change: use another name (Rich Hickey's recommendation). If you provide more or accept less, fine. If you provide less, or require more, use a new route (like a /v2...).
Therefore, refactoring in your code base, which makes your life easier, is transparent to everyone else who depends on your code. We have many small teams, so each team is providing 5 to 10 microservices, and refactoring within each independent repo is simple and low impact.
There's no magic here, we simply paid the upfront cost of adopting an architecture that can be fielded by a very large dev organization, with a concerted effort in high quality DevOps practices. This move was also a means to scale the organization without dragging our efforts to a screeching halt with maintenance burden.
It was probably bad wording on his part when he said “rewriting from C# to Angular”. If he meant, “we created an API in C# and decoupled the MVC rendering from the business logic and rewrote the front end in Angular”, that’s different. Since he didn’t mention rewriting the back end, I can’t assume they rewrote the backend.