I'm currently trying to replace an old (java) testing framework with a different, although similar, one. Therefore, as most occurences of old framework code are the same 90% of the time (in the sense of identic variable names, parameter types etc.), replacing them is pretty straightforward and rather repetitive.
Therefore, I wrote myself a few regex matches (which work just fine, they are not the focus of this question).
However, I have a rather large number of different test files, and I already at this point - just having started - have 6 different match/replacement-pairs that I would like to apply.
Now obviously, being a computer scientist, I would love to automate this, instead of going through every file, pressing Ctrl+F, pasting the matching regex, pasting the replacement regex, pressing the replace button, repeating this cycle 5 more time, and then moving to the next file.
So, let's say for the sake of simplicity, that these are my regexes:
//matches the existing framework
OldClass (.*?) = new OldClass("string");
//replacement regex:
NewClass $1 = new NewClass("string");
//example replacement:
OldClass foo = new OldClass("string");
//becomes:
NewClass foo = new NewClass("string");
So, If I want to replace several of these match/replace-pairs in lots of different files - can I use any built-in eclipse function, or is there an extension that provides this functionality?
Note that I'm aware that I could write a simply java program that just skims through all my source code and applies the regexes as desired.
I'd much rather avoid spending that time, though, and especially would also like to get a chance to apply them individually to each file, so I can re-run the tests afterwards and make sure nothing is broken - which will happen, as not all of the old framework code can be replaced automatically, due to too complex & specific cases. Since I'm also removing the old imports, though, this will break any still existing non-replaced code relying on now-no-longer-existing imports.
Eclipse should have a simple file search option with a "Replace.." button at the bottom. You can search as you would normally specifying the file endings that you'd like to search (probably in this case you'd want *.java). The replace button lets you replace each search result with a replacement using regular expressions.
Granted, this will change your source one replace at a time and that is awkward I know, but my recommendation is to perform small steps, minimizing time in which your code is broken. For instance if you move your class to a new location with a new name, just focus on renaming the class first (verifying that the code then works afterwards), and only then focus on changing its package.
Word to the wise, click Preview first!
Alternatively, consider using ctrl+shift+R to rename methods/variables/classes. Assuming the code is under a source folder, it will automatically rename everywhere it is used. Generally it is preferable to using regular expressions. But again, you can't perform multiple changes at the same time. Though this is probably for the best. Just make a backup of the project and organize the changes that need to be made before starting.
Good luck!
Related
Given the way String pool works for a given piece of code why is it preferred to create a separate file for storing the constants?
String str = "test";
Suppose, the String "test" is used over 50 times in the entire application. Why is recommended to store this in a constants file. Now ,the way string pool works should actually create only one object if it doesn't exist in the pool and then share the references of this object to other places as and when needed. Then why to create a separate constant file to store constants?
The major importance comes with internationalisation, having a strings file means you have a few places in which you have to search for translatable text.
Consider the case when your app becomes a hit and it's being shipped outside of the locale in which it was developed, with a unified strings file, you just have to do a simple conversion of the file content, while with other methods you will have to search every single file and replace every single instance before your application is barely usable to people in different locales.
A very good example is the android resource system for strings. If you keep strings in specific files, it's easier managing them and translating them.
Following advantages you get
Code duplication is avoided across the project. The defined string is constant across the project and can be reused in multiple places
If user want to modify the string value across the codebase, he/she has to change only one place in the file.
Strings don’t clutter up your project code, leaving it clear and easy to maintain
If you want to support localization/i18 support in other languages, then it will be highly useful. Putting strings in resource files makes it much easier to provide separate translations of each string for different languages.
You need some storage for this literals (not only file and etc.) for simple reasons: if you need to change the value of this literal, then you will change it only in one place. For this reasons exists 2 main solutions:
use constant class with public static final Object CONSTANT fields.
use external storage (for example, file)
First case has 2 problems: at first, if you change this values, you will need to recompile project. at second, if this variables used by some frameworks you need to pass this arguments directly in your code. Also, when you need to support of i18n, you could obtain problems with managing right variants.
But when you use external storages, only what you need is implement parser for your storage (I mean json, xml, db and so on). Some frameworks already implement this feature, so you don't need to make this work.
Howevere, you mustn't do it, but it's just really good practice.
Simple: because code duplication is the root of all evil.
Constants are less about performance than about maintaining an application in the long run. As soon as some "property" is used with the same meaning in different places - you want to make sure that all usages are based on the very same definition. So that when updates are necessary, only one line of code needs to be adapted. And not 50, with an ever growing chance of missing to update one or the other occurrence.
Because everything has its place and there's a place for everything. If it's a constant string that, hopefully, will never change and it's used application-wide then logic dictates it (and things like it) should be defined separately for both maintenance and code readability concerns.
That is because if anyone want to make changes in this string in future, then you don't need to search it in whole project. Just make changes in constants file.
I came across a task to internationalise the project which including the code (now 80% of the variable names are in Italian, which need to be changed to English). The translation part is fine, but how to find a way to refactor the code is driving me nuts. Almost every IDE in the market has such refactoring function, but none of them work automatically or programmably.
My question is, do they just use the regex to scan through all the files in the project and then refactor them or follow some sophisticated rules?
I have used a combination of JavaParser and another tool I forget the name of which allowed me to trace usages of all variables in classes from the compiled .class/.jar file.
The JavaParser is certainly a tool that could do the job. I will take a look tomorrow what the other componnet was. Could have been Class Dependency Analyser.
OP appears to want to do mass renaming.
While not the tool you might expect, you can use our Java obfuscator to achieve this.
This solution does mass renaming ignoring scopes, but I suspect that works fine for this.
Many source obfuscators take identifiers and scramble them in a consistent fashion. This means somewhere in the obfuscator, there is map from legacy identifiers to obfuscated identifiers, e.g., "foo" -> "bar" meaning "replace 'foo' by 'bar'".
Our obfuscator reads such a map before it starts (and that's the key to a solution). This map was presumably generated by a previous obfuscation step; reading and reusing such a map ensures that any incremental/additional obfuscation is done in the same way as as the original.
If what you do is run our obfuscator on a set of source files, you get a complete map of every identifier and what it was mapped to (randomly), in a text file looking like (as above):
foo -> i3718234
fas -> h823478
...
If you then run the obfuscator again and feed it the same souces and this map file,
it will (by design) map the identifiers the same way, producing the same result
as the first time.
To do OPs task, one could run our obfuscator on his code to get:
italianID1 -> i23432
italianID2 -> g232343
...
Using a text editor, he could modify this file to:
italianID1 -> englishID1
italianID2 -> englishID2
...
Names he doesnt want touched are edited (obviously) to this form:
foo -> foo
bar -> bar
(A shorthand for this, is to simply leave off the "-> id" part. "foo" by itself is
interpreted as "foo -> foo").
Now running the obfuscator will rename all the italian IDs to englishIDs.
Check out my bio for a link. Its a commercial tool, but its probably cheaper
than a day of OP's labor and I think it solves his problem, waaaaay easier
than building his own refactoring tool.
A downside: I think he'll be forced to reformat his code. That's OK,
the obfuscator includes a reformatter.
I want to create a web site which can be viewed with two languages, one LTR and one RTL. This means that all content should be shown in either of the two languages.
My framework is Spring, and I'm using Tiles2, but I think this question is not framework specific.
The obvious solution to supporting two languages is having everything doubled (all JSP's, fragments, etc.), and you get the part of the tree which fits the language you chose. But this causes problems when changing the web site (you might forget to update the other JSP's), and is not scalable (try doing this for 5 or 10 languages).
I know I can use properties files to host strings for the different languages, but then my web site would be a huge collection of spring:message tags and will be a lot harder to maintain (what happens if I have a paragraph of 100 lines, does this all go into a single properties line?)
Is there any kind of framework, plugin, other, which solves this problem? Has anyone come across a clever solution to this problem?
I've never realized a complete project, just some tests. I think this problem is not so big as it seems if you follow some simple rules. Here is what I would try to do:
Specify direction with <body dir='ltr/rtl'>. This is preferred versus CSS direction attribute.
Avoid different left/right margins or paddings in all CSS. If you must break this rule, probably you'll need to use two different files (ltr.css and rtl.css) containing all these different elements.
Sometimes you'll need to move some elements from left to right or vice versa. For example, in LTR you want a menu on the left, but in RTL you want it on the right. You can achieve this using CSS, but this sometimes is complicated if you are not an expert and you must test it in all browsers. Another option is to use some IF depending on the case. This last option will fit very well if you use a grid based CSS library, like Bootstrap.
Choose carefully which CSS and JS libraries you'll use. Obviously, pick the ones which offer RTL/LTR support.
Don't worry too much about the images. If you must change one image depending on the language is probably because it has some text in it. So, you must use different images anyway. This is a problem related to i18n, not a text direction issue.
Don't let your customer to be too much fussy about it. I think that with these rules (and maybe some more) you can get a good result. But if your customer starts complaining about one pixel here and another one there, you'll need to complicate all this and probably is not necessary.
About your language properties file. Yes, use them. Always. This is a good practice even when you are only using one language: HTML structure is separated from content, is very easy to correct or translate, some words or sentences are in only one file...
Usually, web frameworks are used to build web applications rather than web sites, and there are quite few long static paragraphs. Most of the content is dynamic and comes from a database. But yes, the usual way of doing is to externalize everything to resource bundles, usually in the form of properties files.
Putting a long paragraph in a properties file doesn't cause much problem, because you can break long paragraphs into multiple lines by ending each line by a backslash:
home.welcomeParagraph=This is a long \
paragraph splitted into several lines \
thanks to backslashes.
RTL and LTR is one of the upper and more difficult i18n problems.
Basically its a Problem of the view-scope of the MVC-Model. This may also includes pictures and emotional differences like the color of the skin of people. In this case you better abadon to the solution HTML+CSS gives you.
In example:
<style type="text/css">
*:lang(ar) { direction:rtl }
*:lang(de) { direction:ltr }
</style>
The best practice is to ask members of the audience-group about what effect the webpages have to them.
I agree to most of solutions provided here. Your problem is more design (architecturally) oriented rather than technical. You need to choose path whether you need to keep this logic of internationalization on server (java) side or in static files.
In case you want to go for java side (preferable solution), you need to keep two properties file and use jstl tags. This minimizes your work in case you want to add another language in future. This is maintainable solution. I have seen applications supporting more than 15 languages and time zones. In fact release process gets pretty easy.
In case you want to go for keeping multiple css and other static files, you will soon find things running out of your hands pretty soon. I dont think this is a maintainable solution.
Said all this, I will leave this choice to the architect of application. He will be able to judge which way to go based upon the nature of application and constraints given to him.
You don't want to use everywhere. That's a pity because it is just the way you should do it. It is a bad practice to keep hard-coded texts in a jsp if you need internationalization.
Furthermore, Most of the modern IDE allows you to go to the variable declaration by doing ctrl+left click (or hovering the key) so that having a lot of variables in your code should not be a problem for maintenance.
First, you must distinguish, for each text element, whether it is a user interface element (e.g. button label) or redactionnal content.
user interface element labels will be stored in properties file that will have to be translated for each supported language (and provide a default value as a fall back)
redactionnal content will be stored in a content management system that you will organize in order to find easily a localized version of your content
So this is for an assignment (which I've already completed), I just left this part out because it seemed like a pain in the ass while I was working on the pattern logic.
The assignment asks that you print this menu graphic to help the user decide which pattern to pick. Is there an easy way to do it or do I just need to get a ton of printf/println statements in there? Seems like a very awkward thing to code. Here's an example:
EDIT: This is just for the graphical menu. I know I have to use loops for the actual patterns (which I've already done). The assignment is essentially finished, just missing this menu. I wasn't sure how best to print out this graphic horizontally without awkwardly formatting it by hand.
Text UI has been implemented so many times. Instead of spending some time trying to develop yet another text-based selection/navigation components try to use available solutions:
Fully featured text UI -- Lanterna
Shell-like approach -- JLine
There is another interesting answer, which provides two other, but not so good options.
I think it depends on whether you're going to be assessed on it.
My engineering head tells me that if you're not going to be assessed on it, getting the formatting correct is going to be fiddly and I would just reduce it down to 5 or so println()s, the implementation of which is nothing more than typing.
There's nothing to be ashamed of in such circumstances by choosing what appears to be a trivial exercise. Of course if part 2 of your assessment asks you to extend this to 6 lines (or similar) then a more extensible solution would be appropriate.
I note (following your edit) that you have pattern methods to generate the above. In that case you may wish to modify their inputs/outputs appropriately to facilitate the above. e.g. perhaps they could take in an array of 'n' lines, and append the pattern to those lines, line by line. You'd also need some justification method to pad those lines for the next pattern generator.
I aggressively use Eclipse formatter and clean-up for all my code. Every time I save my source, all my code is formatted nicely, indentation fixed, braces put in correct places and removed where unnecessary, imports are organized, variables declared final where they should be, and other fine little things happen.
It's very comfortable to user, but I'm just curious – are there any drawbacks? May be bad habits that I'll acquire unknowingly?
Reformatting can play havoc with diffs in version control.
If there are multiple developers then make sure formatting is done to a common standard. Agree on a standard, export the formatting rules from Eclipse and put the formatting rules into source control somewhere. Get all devs to check out the rules and apply them.
Better still, use a version control hook to automatically format all source to the standard rules as part of the commit. This way *you will never have to use Ctrl-Shift-f again!
In general, no, the default rules work well. Are you using default values? Are you the lone developer or walking into an existing team / project?
The format and cleanup rules can be altered, tailored, and saved right alongside your source code. In essence, what my format button does may not be the same as what your format button does if either of us moved from the default rules.
The only problem I've seen is on mutil-member teams, if you do not share the same formatting rules, the formatting can result in difficulty comparing changes before check-in. So, for example, if you have a clean check-out then make a small change to ten files then use the synchronize view to compare your changes before check-in, all the spacing changes can obstruct the actual changes you have made. This can, for example, make a code review more difficult.