Generally unused/dead code is bad but I wonder what to do with unused components.
Imagine that I have application that sends notifications to users, it sends EmailNotification but after some time we switch to sending notifications with SMS. Instead of deleting EmailNotification class i create interface let's say Notification and I have such structure:
Notification
--SmsNotification
--EmailNotification
I don't want to remove EmailNotification, because after some time we can go back to EmailNotifications and this change will be as easy as mark EmailNotification class as #Primary.
In such case one of the implementations is always dead code and I wonder if it is ok or generally how to deal with that?
Actually this is not the best practice.
Instead of this practice, you can separate your code into two different modules, one per component. By this way you can utilize any of two modules depending on your needs through your build automation tool (maven or gradle for example). So the produced jars will contain no dead code.
I would agree that this is not dead code, just unused code. However the code in production should be as clean as possible and so if using version control such as git, I would remove the code as it will always be there in the history of the git repository. If you do not want to do this, then I would suggest a way of explaining why the code is there, some thing like a java doc or readme file.
There should not be any problem in keeping the old code, which might become reusable in future. As a matter of fact, the design itself should be so that it can accommodate changes in components without severe impacts.
But if there is an unreachable block of code, which certainly will not add any value to the product in present or future, it will be better removed, because it will unnecessarily increase the number of lines of code and will slow down the process of testing, ultimately impacting the delivery. Additionally, this unused code block will also appear in the final product (the JAR/WAR) unwantedly increasing its size.
In my case, I was using SonarQube for static code analysis and there were blocks of code, methods and sometimes files which will show up only at the time of testing. It was slowing down the process as well as taking otherwise unnecessary heap space. Getting rid of those blocks certainly helped us speed up the process.
One thing you should be aware of is that even unused components need to be maintained. Some examples that come to my mind:
If the Notification interface changes, EmailNotification has to be changed too
If you update dependencies used by multiple components, you by might need change EmailNotification too
If you change or introduce new quality measures (e.g. x% of code coverage, specific code styles, no warnings policy etc.), they also apply to unused components - which leads to additional work
The changes required to maintain unused components could be obvious (because it does not compile any more) or subtly (they still compile but since they are not used, no one notices that they fail at runtime). Even if compile errors get fixed, chances are that they are not getting tested properly.
So by keeping unused modules you might have to do more work than necessary for certain changes and you still run the risk of having a broken module that you can't just turn on when needed. It could easier to just retire the component and revive and update it when it is actually needed. You could wait with the retirement until there actually is a breaking change though. If you are lucky, no breaking change comes before the component is needed again.
If you are certain that you'll need the component again in near future, then keep it. But make sure to maintain it properly.
Related
I have a class (Android Activity) which handles start-up of my application. The application has some pretty complex start-up rules. Right now it looks like a bunch of spaghetti and I'm looking for strategies for refactoring it.
It's honestly such a mess I'm having problems hacking it down to provides pseudo code. In general there are some rules for start-up that are basically codified in logic:
Steps:
Check for error on last exit and flush local cache if necessary
Download settings file
Parse settings and save settings to local native format
Using the values in settings, do a bunch of 'house keeping'
Using a value in settings, download core data component A
Parse component A and load up local cache
During this logic, its also updating the user interface. All of this is handled in a zig-zagging, single monolithic class. Its very long, its got a bunch of dependencies, the logic is very hard to follow and it seems to touch way too many parts of the application.
Is there a strategy or framework that can be used to break up procedural start-up code?
Hmmm. Based on your steps, I see various different "concerns":
Reading and saving settings.
Downloading settings and components (not sure what a "component" is here) from the server.
Reading and instantiating components.
Flush and read cache.
Housekeeping (not really sure what this all entails).
UI updates (not really sure what this requires either).
You might try splitting up the code into various objects along the lines of the above, for example:
SettingsReader
ServerCommunicationManager (?)
ComponentReader
Cache
Not sure about 5 and 6, since I don't have much to go on there.
Regarding frameworks, well, there are various ones such as the previously mentioned Roboguice, that can help with dependency injection. Those may come in handy, or it may be easier just to do this by hand. I think that before you consider dependency injection, though, you need to untangle the code. All that dependency injection frameworks do is to initialize your objects for you -- you have to make sure that the objects make sense first.
Without any more details, the only suggestion that I can think of is to group the various steps behind well structured functions which do one thing and one thing only.
Your 6 steps look to be a good start for the 6 functions your init function should have. If #2 was synchronous (I doubt it), I would merge #2, #3 into a getSettings function.
I'm in the midst of converting a legacy app to Spring. As part of the transition, we're converting our service classes from an "instantiate new ones whenever you need one" style to a Springleton style, so I need a way to make sure they don't have any state.
I'm comfortable on the *nix command-line, and I have access to IntelliJ (this strikes me as a good fit for Structural Search and Replace, if I could figure out how to use it), and I could track down an Eclipse install, if that would help. I just want to make absolutely sure I've found all the possible problems.
UPDATE: Sorry for the confusion. I don't have a problem finding places where the old constructor was being called. What I'm looking for is a "bullet-proof" why to search all 100+ service classes for any sort of internal state. The most obvious one I could think of (and the only one I've really found so far) is cases where we use memoization in the classes, so they have instance variables that get initialized internally instead of via Spring. This means that when the same Springleton gets used for different requests, data can leak between them.
Thanks.
In Eclipse you can just right click on a variable/type and there is an option for References (or Declarations) -> (Workspace / Project / Hierarchy) which can help you find all instances of it neatly.
I would suggest using Eclipse's built in refactoring tool, it will do its best to change every instance associated to the class accordingly. I would go a step further and rename the class of that you want to change so, at worst case, a full compile would fail and you can easily fix any of those issues.
I have a library that deals with several message formats. Each of these formats is closely related, they're a common base XML then each has some additional constraints or extra data on top of it.
One of these formats was created just to support a proof-of-concept or pilot effort. The pilot is over, its no longer being used, and it imposed some awkward constraints. I've gotten permission to remove support for it. What is the correct way to do this?
I'm thinking:
Open an issue to track/document the changes
Tag the SVN revision, "FEATURE_X removed here"
#Deprecate the specific classes. Cite the issue. Commit.
Watch the warnings and see what the deprecation affects
Let it sit for a bit, give the team a chance to deal with the deprecation
Finally remove the code. Verify that the tests are OK. Commit.
I think you have a good list. To echo #hvgotcodes, this presupposes the API is not used by anyone outside your team. In either case, inside the deprecated method, I would log stacktraces for any calls to it. This would catch both internal and external uses.
To the steps above, I'd suggest to clearly communicate to others that the feature will be dropped by the given deadline. And if the feature and/or team is big, I'll suggest get others commitment to remove their code dependencies by that date (the bigger team is, the more important the commitment is, consider managers support for this task). As my experience shows, removing something is a big surprise to a few users, and there is always someone somewhere with somecode that still depends on the FEATURE_X. And last but not least, additional step to do a dry-run removal, that can be easy and quickly undone.
I have an application using AspectJ with load time weaving to advise various methods. I would like to put a switch in my program to disable the aspect without having to make any source code changes or having to restart the program. It needs to incur as little overhead as possible while turned off. Thanks!
To my knowledge, there is no way to unweave some advice from bytecode. If you're working with an existing piece of augmented bytecode, I don't believe there's any way to remove it other than restarting the application without the weaving*.
If you're talking about setting things up so they can be removed - it may be true that the weaving can't be removed, but you could certainly add a global if (useWeavedCode) check around all of it, and of course add that variable as well as methods to modify it in an appropriate way (expose via JMX, new console command, new admin JSP page, etc.). Then if you want to prevent this new behaviour, you can disable it with this new option.
Note of course that this doesn't actually remove the code, and incurs the cost of a boolean
parameter lookup while it's disabled, but I don't think it's possible to do better than that.
*Strictly you need to get the class loaded again, so you don't need to restart the app, but in practice this is likely the most straightforward option available to you unless you've previously put hooks into the classloaders.
I am working on a game in JavaFX and I'm sending people the compiled game once in a while for them to try out. As I'm still in the middle of developing it, I have several pieces of code intended solely for developing/debugging.
One example is a gamespeed slider that is of great use for me while testing, but it is VERY buggy and can only be used in a specific manner - in other ways, I don't want code like that in the test releases.
What is the best ways of removing such code?
Surrounding the code with if(Config.DEBUG) (setting a parameter in code) ?
Using if() but setting parameter in different build configurations?
Can SVN branches keep sort of code like this? Or should I change to Git?
Is there any way to use annotations for this?
SVN branches can be used for this, but you keep ending up with the effort of having to merge your branches every so often. I wouldn't do this.
Though perhaps not wildly elegant, I'd go for your first suggestion: Put a configuration parameter somewhere that your build process can change it for you automatically, and if()s around the affected code.
Change your build process so it will create player jars and testing jars at the same time.
Just use pure if statements, and check if some environment variable or VM option is set, in which case execute your debug code (or test release code, depending on your needs). There should be no performance issues, and the HotSpot JIT might even eliminate these parts.
Sure, it feels somewhat quick-and-dirty to me, but it's simple and it does exactly what you need.
Regarding your other suggestions, using a branch is not a good idea to do this. It's possible, but it will have an overhead you don't really like to deal with. Annotations might be able do the job, but this solution will be more complex than necessary.