I want to change the type of a variable from String to int, can we use Eclipse to refactor?
There's no out of the box refactoring tool that does it as far as I know. The reason probably is that strictly speaking this isn't refactoring: refactoring is a change that doesn't affect the behaviour of the code, but this change definitely does.
Unless you're using reflection, the easiest way to make this change is to change the field first, then watch the bits that turn red, and work your way through them. (You'll get a cascade of errors, pieces that you fix will cause other pieces to go wrong, but eventually you'll get o the end of it.)
I know this isn't really the answer you wanted but if you follow this pattern (deliberately break the code first, then correct errors that arise), it doesn't take long.
If you do have reflection in your code though, then you have no other option than to go through every single file that uses reflection and check whether it would be affected by your change.
Related
Yesterday I made this question: Java function on function
For help and get marked as Duplicate but I think I didn't get understand there what I want and now I try again.
I want methods can be only called on methods for example we have the class Roads and on the road we will go a Way.
Roads.Way1()
After we choose the Way1 we will go to Path1
Roads.Way1().Path1()
But if we choose Way2
Roads.Way2()
We are not able to go to Path1() cause Way2() goes to Garden1() so
Roads.Way2().Garden1()
So what I try to say you can only use the methods(functions) in a wanted way and I saw this on different API or Library. So for the good understanding
Way1 goes to Path1 and ISN't able to go to Garden1
Way2 goes to Garden1 and ISN't able to go to Path1
So how to manager that I can make different roads that has there own ways so I could make like
Roads.Way1().
/*
Goes to:
Path1()
Fountain()
Market()
*/
And Way to cant access them and can only use there own destinations.
I think what you are asking for is: how can I express "control flow" using "language features". And well, there would be ways to get there: you would need a lot of different classes (or maybe interfaces); so something that is a "Way2" would simply not offer a "Path1" method.
But: doing so sounds like bad idea. It will work fine initially, but as soon as you start extending your system, you will be running into problems all the time:
"Hmm, I need to change Way2; it should now allow to go Path1; but uups; there are some Way2-thingies that should not allow Path1; so I actually need a Way3-thingy" and so on. Chances are extremely high that maintaining this code will turn into a nightmare very soon.
I know, this is just an opinion, but my gut feeling is: you are looking for the wrong solution to your problem. Instead, you should spent time on identifying what your actual problem is; and then think about better ways to solve that problem!
Not sure if the title is the most descriptive way of putting it, but it's about as descriptive as I could think of.
Anyway, onto the question. I want to know how I can find similarities in bytecode. What I mean by this is rather difficult to properly explain (at least for me), so I will give an example instead.
I have aba.class, and nhf.class. These classes are obfuscated classes from a game I made. I offer a modified version of this game which simply has some small code changes in some places, but because the game is for sale it gets reobfuscated every time there is a new update. I want to be able to tell what class has changed to what in the reobfuscation by checking how similar the bytecode is for the classes. I know this is possible, but I have no idea how to check how to do this.
Is there a library, program or something that can parse bytecode and check how similar it is, or would I have to write this myself? If I would have to write it myself, I would appreciate someone to point me in the right direction (or link me to something that might help, etc).
Also, I'm looking at doing this with code, rather than manually, in case that wasn't apparent.
There can be a simpler solution:
I don't know what obfuscator you use (maybe Proguard), but it probably generates a map that maps obfuscated classnames to non-obfuscated classnames. (If not, you can switch to Produard, which generates such map.)
So, you can translate obfuscated classnames to original classnames (and vice versa) provided that you have the map for the version.
So, you can make such map from these two maps by matching original classnames.
When I receive code I have not seen before to refactor it into some sane state, I normally fix "cosmetic" things (like converting StringTokenizers to String#split(), replacing pre-1.2 collections by newer collections, making fields final, converting C-style arrays to Java-style arrays, ...) while reading the source code I have to get familiar with.
Are there many people using this strategy (maybe it is some kind of "best practice" I don't know?) or is this considered too dangerous, and not touching old code if it is not absolutely necessary is generally prefered? Or is it more common to combine the "cosmetic cleanup" step with the more invasive "general refactoring" step?
What are the common "low-hanging fruits" when doing "cosmetic clean-up" (vs. refactoring with more invasive changes)?
In my opinion, "cosmetic cleanup" is "general refactoring." You're just changing the code to make it more understandable without changing its behavior.
I always refactor by attacking the minor changes first. The more readable you can make the code quickly, the easier it will be to do the structural changes later - especially since it helps you look for repeated code, etc.
I typically start by looking at code that is used frequently and will need to be changed often, first. (This has the biggest impact in the least time...) Variable naming is probably the easiest and safest "low hanging fruit" to attack first, followed by framework updates (collection changes, updated methods, etc). Once those are done, breaking up large methods is usually my next step, followed by other typical refactorings.
There is no right or wrong answer here, as this depends largely on circumstances.
If the code is live, working, undocumented, and contains no testing infrastructure, then I wouldn't touch it. If someone comes back in the future and wants new features, I will try to work them into the existing code while changing as little as possible.
If the code is buggy, problematic, missing features, and was written by a programmer that no longer works with the company, then I would probably redesign and rewrite the whole thing. I could always still reference that programmer's code for a specific solution to a specific problem, but it would help me reorganize everything in my mind and in source. In this situation, the whole thing is probably poorly designed and it could use a complete re-think.
For everything in between, I would take the approach you outlined. I would start by cleaning up everything cosmetically so that I can see what's going on. Then I'd start working on whatever code stood out as needing the most work. I would add documentation as I understand how it works so that I will help remember what's going on.
Ultimately, remember that if you're going to be maintaining the code now, it should be up to your standards. Where it's not, you should take the time to bring it up to your standards - whatever that takes. This will save you a lot of time, effort, and frustration down the road.
The lowest-hanging cosmetic fruit is (in Eclipse, anyway) shift-control-F. Automatic formatting is your friend.
First thing I do is trying to hide most of the things to the outside world. If the code is crappy most of the time the guy that implemented it did not know much about data hiding and alike.
So my advice, first thing to do:
Turn as many members and methods as
private as you can without breaking the
compilation.
As a second step I try to identify the interfaces. I replace the concrete classes through the interfaces in all methods of related classes. This way you decouple the classes a bit.
Further refactoring can then be done more safely and locally.
You can buy a copy of Refactoring: Improving the Design of Existing Code from Martin Fowler, you'll find a lot of things you can do during your refactoring operation.
Plus you can use tools provided by your IDE and others code analyzers such as Findbugs or PMD to detect problems in your code.
Resources :
www.refactoring.com
wikipedia - List of tools for static code analysis in java
On the same topic :
How do you refactor a large messy codebase?
Code analyzers: PMD & FindBugs
By starting with "cosmetic cleanup" you get a good overview of how messy the code is and this combined with better readability is a good beginning.
I always (yeah, right... sometimes there's something called a deadline that mess with me) start with this approach and it has served me very well so far.
You're on the right track. By doing the small fixes you'll be more familiar with the code and the bigger fixes will be easier to do with all the detritus out of the way.
Run a tool like JDepend, CheckStyle or PMD on the source. They can automatically do loads of changes that are cosemetic but based on general refactoring rules.
I do not change old code except to reformat it using the IDE. There is too much risk of introducing a bug - or removing a bug that other code now depends upon! Or introducing a dependency that didn't exist such as using the heap instead of the stack.
Beyond the IDE reformat, I don't change code that the boss hasn't asked me to change. If something is egregious, I ask the boss if I can make changes and state a case of why this is good for the company.
If the boss asks me to fix a bug in the code, I make as few changes as possible. Say the bug is in a simple for loop. I'd refactor the loop into a new method. Then I'd write a test case for that method to demonstrate I have located the bug. Then I'd fix the new method. Then I'd make sure the test cases pass.
Yeah, I'm a contractor. Contracting gives you a different point of view. I recommend it.
There is one thing you should be aware of. The code you are starting with has been TESTED and approved, and your changes automatically means that that retesting must happen as you may have inadvertently broken some behaviour elsewhere.
Besides, everybody makes errors. Every non-trivial change you make (changing StringTokenizer to split is not an automatic feature in e.g. Eclipse, so you write it yourself) is an opportunity for errors to creep in. Do you get the exact behaviour right of a conditional, or did you by mere mistake forget a !?
Hence, your changes implies retesting. That work may be quite substantial and severely overwhelm the small changes you have done.
I don't normally bother going through old code looking for problems. However, if I'm reading it, as you appear to be doing, and it makes my brain glitch, I fix it.
Common low-hanging fruits for me tend to be more about renaming classes, methods, fields etc., and writing examples of behaviour (a.k.a. unit tests) when I can't be sure of what a class is doing by inspection - generally making the code more readable as I read it. None of these are what I'd call "invasive" but they're more than just cosmetic.
From experience it depends on two things: time and risk.
If you have plenty of time then you can do a lot more, if not then the scope of whatever changes you make is reduced accordingly. As much as I hate doing it I have had to create some horrible shameful hacks because I simply didn't have enough time to do it right...
If the code you are working on has lots of dependencies or is critical to the application then make as few changes as possible - you never know what your fix might break... :)
It sounds like you have a solid idea of what things should look like so I am not going to say what specific changes to make in what order 'cause that will vary from person to person. Just make small localized changes first, test, expand the scope of your changes, test. Expand. Test. Expand. Test. Until you either run out of time or there is no more room for improvement!
BTW When testing you are likely to see where things break most often - create test cases for them (JUnit or whatever).
EXCEPTION:
Two things that I always find myself doing are reformatting (CTRL+SHFT+F in Eclipse) and commenting code that is not obvious. After that I just hammer the most obvious nail first...
Let's say I have a function called DisplayWhiskers() which puts some slashes and backslashes on the screen to represent an animal's whiskers like this: /// \\\.
I might write a comment for this function along the lines of
// Represents an animal's whiskers by displaying three
// slashes followed by a space and three backslashes
But if I then add functions DisplayKitten() and DisplaySealion() which as part of their work call DisplayWhiskers(), how much detail about the displaying of whiskers should go in the comments for these other functions?
On one hand, it seems that I should be able to look at the comments for DisplayKitten() and understand everything I need to about what it's going to do, including exactly how it will display the whiskers. I shouldn't have to go elsewhere to read the comments for DisplayWhiskers() to find this out.
On the other hand, if the comments for DisplayKitten() explicitly refer to three slashes followed by three backslashes, this seems to go against the spirit of encapsulation and could become erroneous if DisplayWhiskers() is later changed.
What is considered best practice?
EDIT: Several answers have suggested that the solution is to read the code. I understand the principle of good code being its own best comment, but for this question I didn't mean to refer to in-code comments, but to the comments in header files that accompany the function prototypes. Let's assume the actual code is pre-compiled and not accessible to the client who wants to use or call it.
I would say that you should write your code clearly and name it appropriately so that it is self-documenting and doesn't need comments for future programmers to understand what it does. Then you would only use comments to document API functions (where the user doesn't have access to the code base) or complex/non-obvious things that you haven't been able to refactor to make them more understandable.
In general, comments should not concentrate on what the code does -- the code itself documents that. Instead they should concentrate on WHY things are being done.
You seem to be naming your functions descriptive enough and leaving them to do only one thing (single responsibility). By reading the code you would essentially understand what they are doing. This would be my preference instead of adding comments.
I'd argue that in general, this paragraph is on the right track for 99% of cases:
On the other hand, if the comments for
DisplayKitten() explicitly refer to
three slashes followed by three
backslashes, this seems to go against
the spirit of encapsulation and could
become erroneous if DisplayWhiskers()
is later changed.
How DisplayKitten() calls DisplayWhiskers(), and even the fact that it calls it, is probably an implementation detail.
There are cases where this is not true. Sometimes you have a "convenience function" whose job is to just call another function in a particular way. In those cases it may make sense to intentionally break the encapsulation in your documentation. These cases are the exception to the rule, however.
Your functions should ideally do one thing only, whatever a "thing" may be and at what level of granularity.
Similarly, they should be described at the appropriate level of granularity. If you're printing out an ASCII kitten, you can leave that as the description for DisplayKitten(). You don't have to describe every last thing it does.
Think about it. If every function described every last thing it did, your main function would have to describe every individual thing anything in the program would do, and that's way overkill. Moreover, most of that comment would be distributed among the called functions, and so on, so the program would wind up as mostly ridiculously detailed comments.
So, leave the comments to what the function does in general, and as long as your function names are sufficiently descriptive (and yours are) cut those to a minimum. If you or your users need more detail, they can examine the code.
Normally I wouldn't mention all the work done by all the subroutines. It could get very tedious. It might be worth mentioning if one of the subroutines does something unusual, or has interesting side effects that would otherwise be unknown.
keep the comments DRY
"for this question I didn't mean to refer to in-code comments, but to the comments in header files that accompany the function prototypes."
You'd probably get different answers if you replace the word "comments" with the word "documentation" throughout your question. I think this addition changes the question quite a lot.
There's a huge difference between an interface that you're committed to, and a few notes about how your implementation happens to accomplish something. You should take the former very seriously, and make sure it contains everything the caller needs to know, and no more. The latter should be kept as far away from callers as possible, so that if you want to change it in future, you can do so without affecting any other code.
In this case, kittens clearly have whiskers, so that much should be documented. But is it a vital feature of kittens that they have three whiskers on each side? I don't know, it depends entirely on the real problem domain, and the design of your code. If not, you probably shouldn't be documenting it, and perhaps should specifically mention that the number of whiskers may change without warning in future.
Method comments (ideally in javadoc form, despite its hideous syntax) should accompany methods, and should include what a caller needs to know to call the method, and nothing else (except possibly what a subclasser needs to know).
What work is done by submethods is an implementation detail. Indeed, whether there even are any submethods is an implementation detail.
Just tell potential callers what they need to know, things like: does displayKitten() actually display a kitten? If so, where? Or does it return a string representation?
Should you give the format? That depends. Is the actual representation of a kitten an implementation detail, as described in the question? In that case, no, you should not give the format. But if it's in compliance with some specification, it's good practice to reference the spec - possibly even in the method name: displayKittenPerFsda246_a().
We've got a fairly large amount of code that just made the jump to Java 5. We've been using generics in those components targeted at being released in the Java 5 version, but the remaining code is, of course, full of raw types. I've set the compiler to generate an error for raw types and started manually clearing them, but at the present rate it'll take a very long time to go through with it (there are about 2500 errors). And that's with Eclipse's helpful Infer Generic Type quick fix, which always gets rid of the errors, but often generates code that needs further work.
Is there any better way to dealing with this? Are there any automated tools better than Eclipse? Any way to apply the refactoring to all occurences instead of doing them one-by-one? Or do you just ignore the warnings?
I would suggest ignoring the warnings. Otherwise, you'll be putting a lot of time into updating the legacy code without making any improvements to its functionality.
Update: Great comment from Luke that I thought should get more visibility:
"Generics are a way to catch run time bugs at compile time. Unless this legacy code has bugs in it that you think are related to casting I would leave it alone (if it ain't broke, don't fix it)"
As far as I know, you're going about it as efficiently as possible. It's
obviously not perfect, but you'll finish eventually.
I recommend that you do it in stages, however; there are likely parts of the
code that would benefit more from this than others, focus on those. Trying to
do it all in one sweep runs the risk of introducing new bugs to your code. We
have one such place where we have a collection that holds context-dependent
data, and generics actually can't work for it.
Basically, do what you're doing, but do it in stages as part of other work,
instead of trying to fix it all in one throw.
Faced with a similar challenge, we opted to upgrade to Java 5 style generics only in the code that was edited for another reason. So if you have a bug to fix in DoItFast.java, update DoItFast.java to use Java 5 style generics. The areas of the code that are being edited and changed regularly will get updated quickly. After a few weeks or months of this behavior, you can reevaluate the condition of your code base.
If that doesn't get the job done fast enough for you, sometimes I'll use the slow time after lunch to just mindlessly cleanup a few classes and speed the process along.
I don't think it is necessary to update all the old code. Maybe if you could somehow identify which parts of the old code are used frequently, and only update those to use generic types? Or maybe you could only worry when the raw type is returned from a public function? A lot of these cases are probably just private/local variables, which are already written without generic types and presumably work just fine, so it's probably not worth the effort to rewrite them.
I understand with IDEA you can select all your classes, popup the context menu and select Refactor | Generify. Job done. It's certainly a more enjoyable experience to work with generified code (IMO).