7 ms·
Systematically removing code
- paulie_a 6y agoI found pycharms "find usages" to be extremely useful. Im assuming the jetbrains ruby version would have something very equivalent.
- Nextgrid 6y agoIt's not 100% reliable though. There are plenty of ways to resolve a Python symbol at runtime with no way to statically resolve it.
- spdionis 6y agoHonestly, at least in modern PHP, people just avoid using that level of dynamicness or explicitly annotate it where possible. I will require changes in code reviews if PhpStorm cannot analyze usages in your code.
- deleted 6y ago[deleted]
- bhaak 6y agoOr you remove that line and let your test build run. If it's being used, it should be tested, and then your test will complain.
- npsimons 6y agoWhile I laud the idea of having tests that reach 100% coverage (only half being snarky here), I feel that this is a bad habit to get into, just mindlessly changing things and assuming your tools will catch it.
- henrikn 6y agoHi! Blog post author here. I agree that tests are super valuable for many things, but it isn't enough here – at least not with the way my team writes tests. (Our) tests wouldn't catch unused CSS classes or i18n keys. (Our) tests wouldn't catch an unused method that is unit-tested. The unit test would happily pass because the unused method is still around and does what it should… in a vacuum. Tests are great for catching live code that was incorrectly removed, but I'm not sure how they would help catch dead code that was incorrectly left in – but would love to hear more about it :)
- furstenheim 6y agoSomething that I've thought sometimes. A tracing mechanism in all branches. And you check in production which lines are never executed. Of course, some things are tricky. For example, handling of cases that should never happen, but maybe those could be annotated.
- fhars 6y agoPeople have actually automated ideas like that: https://news.ycombinator.com/item?id=25059134 https://news.ycombinator.com/item?id=25059134
- twic 6y agoYour interpreter or JIT already knows exactly what gets executed. Is there some way to get it to tell you?
- furstenheim 6y agoDatadog is providing tracing at least at a function level, so it should be possible
- drchopchop 6y agoThis illustrates one of the biggest downsides of dynamic languages - refactoring. Compile-time checking saves you from having to detect copy/paste/delete errors at runtime. A good IDE can help, but it's no substitute. This is especially problematic in Ruby, as the author mentions, as the language is so dynamic that you're stuck having to write 100% coverage to ensure that variables are even named correctly.
- horsawlarway 6y agoI don't really know how much type systems help here. I'm not really aware of a type system that enforces code actually be called. I know lots of linters do check for unused code, but generally only at the local level (ex - you imported/included X but never called it) I agree 100% that it saves time during refactoring, but it's not going to catch that your NicheHelper class that was only called in one place is not called anymore. Nor is it going to find and highlight css that can be ditched as well.
- thrower123 6y agoAll of the JetBrains tools will do complete project analysis and find unused code, and Visual Studio is approaching this level of functionality out of the box - with extensions and Roslyn plugins it is possible to do some very powerful checks. Dynamic language tooling is really like banging goddamn rocks together, and people take pride in that...
- PaulKeeble 6y agoPMD for Java does as well with the right settings.
- Scarbutt 6y agoI will take a dynamic language over bad statically-typed languages any day, no matter how good the IDE is.
- thrower123 6y ago
- turadg 6y agoRemoving dead code is something we could have much better automated tools for. I’m thinking like https://github.com/uber/piranha https://github.com/uber/piranha on steroids. What would you pay to have a service that did this automatically on your codebase? You remove something in a PR and it adds a commit that cleans up everything else that can be.
- brundolf 6y agoFor a fully static language, it wouldn't contribute much value because existing tooling can do that already. For a dynamic language (like in the OP), it would be an impossible problem to solve perfectly and I wouldn't trust it to be automated.
- ozim 6y agoFor big web applications or an API, even if they are build in static language you still cannot just remove an endpoint. Maybe something is calling that endpoint once a month and you don't see it, maybe even less, then you only will get to know a lot later.
- brundolf 6y agoNo matter what, you could only ever hope to verify things that you know can only ever be called by the very code being analyzed. Proving the negative is what you're really trying to do. So static languages can exhaustively prove "deadness" for any non-exported definitions, but external APIs - be they functions or web endpoints or otherwise - are outside the scope of the problem.
- anton_gogolev 6y agoThat’s not called “deleting old code”. This is now “breaking backwards compatibility”.
- karmakaze 6y agoThis could be done by fuzzing and running tests. If the tests pass with code removed, then either a test that exercises the wanted code could be added or the removal accepted.
- kevsim 6y agoThe #1 place I struggle with this is with deleting CSS. I know we've got unused CSS hanging around, but because of the cascading/matching behaviors of CSS, I'm way too scared to delete any of it. I guess that's a strong argument for Tailwind and other CSS-in-JS frameworks, since the CSS disappears when the JS does.
- henrikn 6y agoAgreed, this can be difficult. An approach like BEM can help somewhat because you rely less on cascading. But then again, because it's tediously explicit, one may generate BEM class names in Sass or with PostCSS in a way that makes those long, explicit names harder to grep for…