Live data from Hacker News

Evolutionary couplings between files reveal poor software design choices

ergoso.me

41–50 of 85 posts

Re: Evolutionary couplings between files reveal poor software design choices

#41
post #9
post #4

I think it is a mistake to think of coupling caused by TDD to be a false positive. What this outlines really is that TDD will force you to edit two files instead of one for many changes. This is a clear indication of how TDD will slow you down.

0. It has nothing to do with TDD 1. It's a tooling artefact, testing systems certainly don't have to mandate split code and tests. Rust's test framework allows tests in the same file as the tested code, the testing guide recommends that unit test live alongside the code they test[0] and the standard library follows this practice[1]. I'm reasonably sure you can also do so in e.g. py.test[2] 2. I'm not convinced editin…

0. It has nothing to do with TDD

OP is referring to this line:

It also turns out, in both softwares, a majority of the couplings are attributable to Test Driven Design, where a source code is coupled to its test. So these are apparently false-positives I should take care of in the next version of the pipeline.

Re: Evolutionary couplings between files reveal poor software design choices

#42

There's some really interesting thinking here, but interpreting this naively would suggest that the perfect software project has only 1 file.

that is partially true: single file apps will never have couplings in this manner. One extension to this project would be to find couplings between particular regions of the file and then even single file apps will start falling down. I think it is not true that if you cannot find any coupling using this tool, your software is well-designed; it would just mean this tool is not smart enough to capture those bad designs.

Couplings between different regions of the files, however, are relatively harder to find and requires some more thinking in terms of implementation.

Re: Evolutionary couplings between files reveal poor software design choices

#43
post #21

I'm running it now on a repository with 15 years of history, and ~15K commits. Let's see how it goes. :) One thing I noticed is that the scripts are written to run once, and always do everything. It would be better to have a Makefile and dependencies, so that the you can run it multiple times, and only the changes are updated. I'll see if I can push some fixes to github.

let me know if you find points that can be improved; I would be more than glad to pull your changes in to the main repository.

Thanks for trying this out.

Re: Evolutionary couplings between files reveal poor software design choices

#44

Are there undocumented flags that you're running this with? I wind up with a series of graphs too densely packed to make sense of when I run it on angular.

The PDFs that come out of igraph layout are not that pretty. The screenshots I used on the blog post are generated with Cytoscape 3.1.1, which gives better layout and better styling options. For Angular.js, I went with "partialCorrelations_0.3.sif".

Re: Evolutionary couplings between files reveal poor software design choices

#45
post #6

I played around with this a bit in June. This is what I managed to come up with in the time I was interested in it: https://bitbucket.org/brysgo/git-coupled

cool! Thanks for sharing the link to your project. I am not really a Ruby expert, so wasn't able to figure out how you calculate the couplings. I will be more than happy to compare the results across these two tools.

Re: Evolutionary couplings between files reveal poor software design choices

#46
post #3

A "correctly layered" app with UI view separate from UI logic separate from server-side logic etc. will show up as coupling, if commits are feature oriented. There's certainly a hint as to where to look for bad coupling, but expected "coupling", like tests, need to be discounted.

> A "correctly layered" app with UI view separate from UI logic separate from server-side logic etc. will show up as coupling, if commits are feature oriented. It would show some coupling commits, but e.g. bug fixes should/would be segregated to the relevant files, not spread across the system.

Basically bugfixes would be localized to relevant files, but features would spread across files.

The grandparent's making an important point in that you can't design a system such that all possible changes you might want to make are localized to one area of the code. Engineering is about trade-offs: if you rigorously separate view from logic from database, you make it harder to add features that must touch all three. Conversely, if you make each feature its own file and add in hooks to the view/logic/database layer so they call out to plugins, you make it easy to add new features but very difficult to understand what each layer as a whole is doing.

The best you can do is choose the ideal architecture for your particular project, in the particular point in time that you're working on it. That's why basically every software system needs to be rewritten as it grows up: the ratio of complete rewrites to new features to bugfixes to maintenance refactorings changes as the system matures and the requirements become more precisely known. It's also why we have a software industry; if there was one ideal way to design a system for all domains and all points in time, someone would go design it and be done with it, and none of us would have jobs.

Re: Evolutionary couplings between files reveal poor software design choices

#47
post #16

The first two times I read this headline I thought it was about fruit fly evolution.

I know, right? I was really happy when I learned that this branch of the CS is also referred to as evolutionary, because I was inspired by the evFold approach, which is related to evolution in multiple organisms. This is a bit confusing for people coming from the biological science domain, but also nice that we share some terminology between two fields ;)

Re: Evolutionary couplings between files reveal poor software design choices

#48

Am I the only one who disagrees with the premise that two files that tend to change a lot together indicate poor software design choices? If you change an API, you will have to change consumers of the API. Does that mean that your code is bad? This exists even in a low level examples: if you change a c++ class, you will need to also change the corresponding header file. Or perhaps, am I misunderstanding the concept?

I think what's clearer is that bad coding is one reason why we often have to change too many files at the same time. We see software where implementation details surface in so many places that you have to change five files to change anything.

Now, it's affirming the consequent to say "you change two files, therefore you must have repeated yourself/coupled two things too much", but if you think those are common problems, then it will still be sound to say "you repeatedly changed these files in sync, you should look there to see if you've coupled them too tightly."

Re: Evolutionary couplings between files reveal poor software design choices

#49

Earlier quoted context omitted.

> A "correctly layered" app with UI view separate from UI logic separate from server-side logic etc. will show up as coupling, if commits are feature oriented. It would show some coupling commits, but e.g. bug fixes should/would be segregated to the relevant files, not spread across the system.

Basically bugfixes would be localized to relevant files, but features would spread across files. The grandparent's making an important point in that you can't design a system such that all possible changes you might want to make are localized to one area of the code . Engineering is about trade-offs: if you rigorously separate view from logic from database, you make it harder to add features that must touch all three…

> if you rigorously separate view from logic from database, you make it harder to add features that must touch all three

I've found the exact opposite of this to be true.

Re: Evolutionary couplings between files reveal poor software design choices

#50
post #30
post #12

Earlier quoted context omitted.

> This is a clear indication of how TDD will slow you down. Not shown: the part where the critical production bug you introduced was caught by your test suite, thus saving you countless hours of agony, angry customers, and lost revenue.

Instead of writing tests in a separate file, why not express the same logic in the form of types in the lines directly above the code which implements that logic? This has the added benefit of making your code self-documenting and giving rise to powerful tools such as type-guided implementation inference and search.

What type system do you have in mind? Haskell?
Post reply on HN