質問

Whenever I write a piece of functionality from scratch, it's a good and robust code.

But often times my assumptions about how the code should work evolve over time. After I reflect those changes in the code, the whole system suddenly loses its quality.

It seems to me that the best approach is to drop the old code and write a new one from scratch with new assumptions in mind. But from obvious constraints in time I wanna learn how to keep the code quality high while heavily changing it.

Question: Are there any techniques or books that could help me develop this skill?

I see how code review is a good tool to uncover issues in code and I agree. But I'm interested in preventing those issues from happening in the first place and developing the skill to do that on my own without involving other team members.

PS: Please don't confuse this with refactoring, which is meant to change the code, while keeping the behavior the same. In my case when the requirements to the code change, it's obviously not refactoring and involves changing the behavior.

役に立ちましたか?

解決

What are the techniques for keeping the code quality high when requirements change?

Have you tried Test-Driven Development? It's exactly for this purpose. When you're done with a feature with TDD, you don't just have the feature, but also all the automated tests that cover that feature. As new features or changes come in, you can run these tests and be sure nothing broke. This will aid you in safely improving the structure of the code, before and after implementing changes.

Which leads me to the second point:

PS: Please don't confuse this with refactoring, which is meant to change the code, while keeping the behavior the same. In my case when the requirements to the code change, it's obviously not refactoring and involves changing the behavior.

As you said yourself, the issue you're facing is that code quality degrades after each change, so eventually the codebase will require refactoring, otherwise you may reach a halting point in productivity. There's no escaping it.

However, perhaps you meant simply that you don't want answers such as "Just refactor the code", which is fair. But this is exactly what your question is asking for here.

Also, an answer to this question could not be complete without a Kent Beck quote:

When faced with a hard change, first make it easy (warning, this may be hard), then make the easy change.

To add a bit of context, when Kent Beck says "first make it [the change] easy", he's talking about refactoring the current codebase to make it more welcoming to the new requirements which we now need to implement.

他のヒント

Whenever I write a piece of functionality from scratch, it's a good and robust code.

We all think that at this point. We're seldom right.

But often times my assumptions about how the code should work evolve over time. After I reflect those changes in the code, the whole system suddenly loses its quality.

Well no. It never had quality. If it had you'd have been able to change your assumptions easily. Quality is more then satisfying today's requirements.

It seems to me that the best approach is to drop the old code and write a new one from scratch with new assumptions in mind. But from obvious constraints in time I wanna learn how to keep the code quality high while heavily changing it.

If you simply can't write flexible code then a rewrite is the best. Certainly better then half mutated code that is still trying to satisfy requirements that no longer exist.

Question: Are there any techniques or books that could help me develop this skill?

From the development point of view this is agile. Waterfall doesn't react well to lots of unplanned and emergent changes. Right now agile is the best we have for this.

From a coding point of view the best principle for this is single responsibility. Each module should have only one, preferably unique, reason to change. Make your decisions in one place. Don't spread them around. Follow that from the start and change won't be so traumatic.

I see how code review is a good tool to uncover issues in code and I agree. But I'm interested in preventing those issues from happening in the first place and developing the skill to do that on my own without involving other team members.

Code review is mainly a check that your code is readable. Definitely worth while but it won't guaranty everything. Others may check your design and implementation but don't lean on that.

PS: Please don't confuse this with refactoring, which is meant to change the code, while keeping the behavior the same. In my case when the requirements to the code change, it's obviously not refactoring and involves changing the behavior.

True. Refactoring changes design. You need transformations to satisfy new requirements. Guess what? Refactoring allows you to change old designs that didn't anticipate a need to accommodate change into ones that do. Once you have that you're ready to write new unit tests that reflect your new needs and can make them pass.

We don't recommend books here but this answer has enough buzz words in it that you should be able to find some now.

Bugs, presence of unnecessary code, that was needed before and isn't need after the change, code reduncancy, bad abstractions, etc. All kinds of bad things.

Adhering to your description of quality of the code, seems reasonable to me to introduce static program analysis in the project's lifecycle. No need to mention that tests are a must (unitary, Integration, functional, end-to-end,...).

The metrics supplied by the static analysis are fairly good at describing objectively the quality of the code in the terms you have expressed.

Sometimes, the analysis can teach you about doubtful practices you didn't know.

What the static analysis can not say is: how good/bad is the design, how bad/good is the model or how efficient or inefficient is the system. At least not the tools I know.

The process can be enhanced introducing programming techniques like peer review or pair programming.

Getting involved one more developer (or two...) makes a big deal better the learning process. The contrast of point of views, skills and knowledge may help to improve those points the static analysis could not.

But I'm interested in preventing those issues from happening in the first place and developing the skill to do that on my own without involving other team members

Regarding to your skills, preventing is a matter of being aware. Developing skills is a matter of time and practice.

It seems to me that the best approach is to drop the old code and write a new one from scratch with new assumptions in mind. But from obvious constraints in time I wanna learn how to keep the code quality high while heavily changing it.

I don't know if It's best or just desirable but I tend to think alike. The time is a relative constraint. In some cases the goal worthwhile an extra effort, overall when the goal is practice and self-improvement.

Question: Are there any techniques or books that could help me develop this skill?

Absolutely. The number one, go to book for maintaining code quality while changing the design is Refactoring. It describes a process for taking what you have and changing it to what you need while all of the time keeping an operational system. By combining the refactoring methodologies with test driven design and a functioning version control system, you gain great power over the code.

Rewriting from scratch is something I used to do a lot. While very tempting, there are a lot of reasons for not doing it. If you start with the code you have, you already have a working system, a testing structure, and a suite of tests that allow you to know the health of your code at all times. By refactoring your existing code, using small and large refactoring steps, you find that you are never more than one or two commits from going back to a working state. This give you great freedom to explore the solution space.

Yes, perhaps the majority of writing about software architecture is really about writing code which is adaptable in the face of requirements change.

If you think about it, most design principles are pretty irrelevant if the code is never going to change. Why even have readable code if you are never going to look at it again? Following principles like SOLID only really pays off when you have to change the code.

Some important principles to that end are "separation of concerns" and "single responsibility". The objective is to separate the code into units such that a single requirements change will ideally require changing a single class or module. The flip side is the YAGNI principle, which says you should not try to predict and prepare for specific requirements changes which you are not sure will happen.

You should ask yourself why your requirements are changing so heavily so often. Is it that maybe you did not understand the requirements properly in the first place and write code to build up this understanding? In that case it makes sense to build one to throw away and then build it right the second time. But even more sensible is understanding the requirements before writing code. Think about the business problem being solved, and then model it at a conceptual level. Who are the users, what are the flows that they will take through the software, what are the types of objects they will manipulate, which actions exist on those objects, what are the data flows in the system, etc... You want to pass your ideas by users, or people who understand the users, with mockups and prototypes.

With a proper understanding of the real world problem being solved I find it is rarely the case that you need to make massive changes to the requirements. You may need to extend them, or tweak smaller points, but big changes won't happen as long as the problem itself remains unchanged.

ライセンス: CC-BY-SA帰属
所属していません softwareengineering.stackexchange
scroll top