sagenschneider
Joined 4 months ago
Joined 4 months ago
I'd be interested to see what happens:
- to token counts after a year of so of changes, as the specification list grows?
- how it goes with concurrent changes in teams?
Plus whether asking AI to add good commenting to the code could achieve the same thing?
Instead of focusing solely on the complexity of the thing you change. Include the context around what you are changing also.
This allows the Change Impact formula to differentiate between two different files of the same length. One is a complex god class with high CC. The other is an entity module that is simple but just has a lot of methods due to properties. Adding to the god class really should warrant a refactor. Adding to the entity class is just another field to store for the entity. The Change Impact formula can differentiate and point to the god classes.
The code becomes a reflection of that.
I'm interested in your experiences of capturing specifications and user discussion on whether this captures the end intentions? Or whether it keeps you focused on earlier dead end directions?
The research I'm actually doing is comparing:
- mutative architecture (Spring) which as single method handling the request. It grows in complexity as changes are added
- additive architecture (OfficeFloor) which does function injection. A pipeline of functions, where new functionality is an injected function as a step in the pipeline (i.e. adding functions, rather than mutating a single handler function)
What I've found is the complexity of the overall system is what it is. Between both architectures, the overall CC is the same. However, the distribution is very different. Mutative architectures pile changes into god handler method. Additive architectures spread the complexity into smaller manageable files.
This, however, does not come with perfect wins. Spread also means AI doesn't read the dispersed files. AI is good with complexity and tends to fix things when it sees them (so does fix bugs in god classes). But this is only to a certain point when the complexity then comes to overwhelm the AI.
The formula is trying to catch the mess of on going changes at a point before the expensive refactoring or rewriting becomes necessary.
However, I'd bring in Brooks discussion on essential and accidental complexity. In other words, there being No Silver Bullet https://www.cs.unc.edu/techreports/86-020.pdf
The problem with specification and user discussion is they still have errors that code has. But unlike code, there are no tests to confirm correctness.
So now we have a definition of the system in a non-exact language with no ability to test to confirm it's correctness. The code holds the essential complexity and now we are adding accidental complexity on top to manage.
Again agree the specifications and user discussion provides context for the AI. However, a well written test suite provides similar context that can actually confirm correctness of the system.
However, saying all the above. Focus of ImpactGate ( https://impactgate.officefloor.net ) is about erosion of the code, not correctness.
It's looking at the nature of on going changes.
A single complex file written once and never touched is likely a good cohesive file about a single problem solved.
However, if we start making many changes to that file increasing it's complexity, it's likely not the problem getting more complex. It's likely we're adding more purposes to the file, eroding it's cohesion. This is the signal I'm trying to catch to avoid a mess starting.
The novelty of Change Impact is it looks at the context of the complexity. Adding complexity to something already complex should be flagged for review.
I've not come across any static code analysis so far that has provided this.
And in my own research of architectures, I came to this formula.
The problem with cohesion is understanding what is "single purpose". Nothing can determine this without interpreting the code and making a judgement call on whether it needs to be refactored into two or more classes.
So I'm looking to approximate this. Instead of looking for cohesion, Change Impact formula approximates this by looking at existing complexity in the file.
If the change adds more complex functions to an already complex class, it scores high. Smell of it doing too many things.
If the change adds a complex function to an empty file, it's likely just a complex single problem.
If the change adds simple change to complex file, then if this happens too many times, we flag it for concern. Especially if it changes a lot of other files too.
So it's not mean to measure your code exactly. It's meant to highlight smell that needs investigation. And the formula points out the classes that need looking at.
Plus I'm not sure that all changes are equivalent. I'm not looking at single one off changes. I'm looking at 60 changes in a row. The first 20 might go through fine. However, after the changes pile on, there needs to be some refactoring to keep the code clean. This is trying to catch it before it becomes a mess.
Though to the bigger point of your comment, yes SDLC are becoming faster. We can churn out code at a ridiculous rate. However, doesn't mean it's good code. And hence, there are studies showing things actually slowing down because reviews pile up.
I guess I look at the Change Impact formula (and https://impactgate.officefloor.net implementation of it) as threshold tool. Small changes that aren't contributing to god classes, just let through. When things start to smell, the files involved get marked for review.
Ideally this then can cut down on review time and allow overall increased velocity.
But yes relies on trusting the AI to do "simple" things
I was testing the additive pipeline style of OfficeFloor against the mutative handler style of Spring. I was looking to see what factors could be used to allow AI to make long on going changes (experiment is 60 changes to an end point, where all add functionality and every 4th change is mutative on existing rules). Then I watch how AI manages to make the 60 changes in each architecture.
I've done many runs and you are quite right about Goodhart effect in giving it the metric. Never knew Spring code could be written so badly.
I've tried runs with better prompting also and I'm starting to find the key factor is actually the architecture itself.
From my initial findings, it's seeming that additive pipeline architectures hold up much better against AI slop than our typically single method web handler architectures.
High cohesion means the functionality of a component are closely related and focused on performing a single well defined task. Basically single classes for single purposes.
Erosion of this is when classes start doing to many things, in the case of God classes.
The Change Impact formula looks at a way of detecting when the cohesion is eroding and flagging it on a change (as the pull/merge request itself should generally be single focus cohesive change)
Yes, there are generally complex algorithms but they usually are not things developers write (imported from libraries).
What is usually going on in the god class/method is that things keep getting added to it. These things should be separated out. So the cohesiveness of the class/method erodes into doing too many things.
The idea of the Change Impact formula is to catch this early so you start refactoring to separate out into classes with single cohesive purposes.
The problem with AI is it handles complexity really well and will happily keep piling changes into god classes/methods reaching ridiculous CC levels (have see over 200). Previously developers would get annoyed and do the refactor. But with AI these days, changes are happening faster. So Change Impact is to try to monitor the cohesive erosion.
https://sagenschneider.blogspot.com