Is there a simple way to find dead jbase code? A specific example of dead code is something like:
x = "a"
if(x = "a"){
do some stuff
}
else {
do some other stuff
}
For the above fragment there is no way the "do some other stuff" could ever be executed. Having a way to identify and find dead code would be very helpful, because older programs are sometimes bloated with lots of dead code, which makes it difficult to figure out what the program is actually doing.
jcover is a utility in jBASE that can assist in detecting dead code during the runtime. I in
https://docs.zumasys.com/jbase/tools/jcover/
If the -x option was used, you can display a list of all the lines of source code not executed with:
LIST jcover_23 NOTEXEC
If the -u option was used, you can display a list of all source items that didn’t have any code executed during the application execution
LIST jcover_23 NOTUSED
Related
I need to do refactoring in a big legacy Python code base.
Often I think "these lines don't get executed in production any more".
But I am unsure.
There are some tests which touch these lines. But I can't tell for sure if really no usage happens in production.
What can I do in this situation?
This question is about coverage on a production system. This question is not about coverage during testing/CI.
I don't want to comment out that lines, since I don't want to produce an error in the production system.
Common practice is to use logging inside that lines of code. e.g. you have a block of code you think is not in use. You add try catch block in the beginning of that block of code. Inside trycatch you add line to a specific json named same as your suspicious block of code.
try:
with open("block1.dat", "rb") as file:
activity = pickle.load(file)
curtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
currentact = "dt = {}; code done that: var1 = {},
var2 = {}".format(curdate, var1, var2)
activity.append(currentact)
file = open("block1.dat", "ab")
pickle.dump(activity, file)
file.close()
except Exception: pass
You can use telegram api to log code to. After a while You'll get info how often your code works and what does it do.
Then you monitor for a while and if nothing happens in a month, You can comment the block.
Is the production system deterministic?
Is it interactive?
Does control flow depend on input data?
Do you have access to all possible inputs?
Do the tests exist for a reason or just because?
I'd be careful removing code based on what is needed based on logging unless I knew there are no exceptional situations that occur rarely.
I would follow the common code paths to try to understand the codebase piece by piece in order to figure out what can be simplified. It's hard to give more specific advice without knowing more about the system you're dealing with.
We use a simple pattern to handle this: looks_like_dead_code(my_string)
This is a method which logs the string "my_string".
Example usage:
if ext == '.jpe':
looks_like_dead_code('2018-11-30 tguettler: looks fixed in mime_type_to_extension')
Using the date and the developer login is not enforced, it is just best practice.
If the line gets executed the one who is responsible for checking the logs will talk to the developer.
Since our production environments get updated roughly once in two weeks, you can be sure that this line was not executed during the last months.
I like this solution since in most cases it is like this:
you want to fix a bug or implement a new feature
you look at the code and see some lines which look like dead code. I mean code which is useless, since it won't get executed any more.
You don't have hours of time to investigate. You can dive into your vague guess that this is dead code. You want to do your actual work (fix a bug or implement a new feature. See Step1)
The method looks_like_dead_code() gives you a way to actually do something and leave a note for other developers. It only costs some seconds improve the current situation.
If you have a Tickler file System you can remind yourself to check this code in six months. At least in my context I can be very sure that this is dead code if this line was not executed for several months.
I want to watch the flow the execution of my ruby code when I am in the console. For example, if I have this :
def process
hash = {a:1,b:2}
hash.values.map!{|e| e+1}
end
And I want to see something like this in console when I type process :
hash = {a:1,b:2}
=> {:a=>1, :b=>2}
hash.values.map!{|e| e+1}
=> [2, 3]
Is there a useful way to do something like this?
$VERBOSE doesn't seems to do anything and $DEBUG seems as the opposite to be too verbose.
You're talking about "trace" functionality.
Some languages, like shell and good-ol' GWBasic, have a flag to show their currently executing line. Ruby's $DEBUG output can flood you with information overload, not so much from your code, but from any gems that look for it and dump their current state or turn on their tracing.
Many people sprinkle their code with puts to have it show some indicator of where they are, during their development/testing. If you do that, I'd recommend writing it as a method to bottleneck your output and let you easily turn it on/off. Also, use a flag to check whether you want to debug. You might even want to use OptionParser to let you create a --debug flag to pass on the command-line. Another nice side-effect of using a method is it's easy to redirect the output to a file you can tail and watch the output as it occurs, and later use for triage.
Another alternative is to load the code into the debugger and tell it to trace. You'll see every step of the code, which is very verbose, but the detail is good. You can also tell it to run to certain points so you can poke at the code and dig around, dropping into IRB if needed.
Personally, being old-school and having cut my teeth on assembly-language, I'm comfortable in debuggers, so I use Ruby's a lot. It's easy to tell it to run to a certain spot and stop, or you can embed include 'debugger'; debugger into your code and it'll stop at that point. Once there, it's possible to see what's going on, then c to continue, and let the program run until it hits the debugger statement again. I find the debugger to be very powerful and a nice selective magnifying glass for those times I want to know what's going on.
"Debugging in Ruby" has lots of nice tips you might find useful too.
EDIT:
I like Alex D's suggestion to look into Ruby's set_trace_func. I haven't used it (and, frankly forgot about it), but that'd be a good way to set up a nice trace in an app. With a little code you could set up toggling it on/off and selectively outputting given a certain class or condition since you're in control of the proc being called.
One option would be to use set_trace_func (http://apidock.com/ruby/Kernel/set_trace_func) to set up a hook which will print out each line as it is executed. Be aware that may overwhelm you with a bunch of information on the internals of irb.
Another option would be to dig into the source code for irb and add an option to print each line as it is executed.
Have you tried the pry gem? Put require 'pry'; binding.pry inside your code and run your script. You will have a ruby console just where your put it. Maybe that is what you are looking for.
Otherwise you should take a look at a ruby debugger.
I am working on a code parser that is built on Rexx. It is a single file script with around 5000 lines of code or more. I've never worked on Rexx before. Adding to that, the readability issue is making my life even tougher. So,
Are there are any tools to debug and understand Rexx code?
Use the trace statement? The most simple mode of tracing is 'A'. This causes each instruction to be displayed before it is executed. Your instruction is displayed with a line number and the three characters - preceding it, so that you can identify it as a line in your script.
Wikipedia has a pretty good article on Rexx, which should help you understand Rexx syntax and program structure. And almost any Rexx book will apply to your environment, because Rexx is extremely cross-system (similar in that way to the younger Perl and Python languages). There aren't a lot of online books, because almost everything written about Rexx was written before the web existed, but the reference manual for the Regina implementation is, and it's a particularly good reference work.
The date on this question is old, but I'll share what I have found helpful for the next person who pulls this up.
Already mentioned is the TRACE option. I've found this can be overwhelming in a small set of code let alone 5,000 lines or more.Here are some options I've found useful:
Use an "if" to turn the trace on only in certain situations.if counter < 25 then trace "A" Be sure to turn the trace off with:else trace "OFF"
Use say followed by pull. What is said will stay on the screen until you hit enter.
Add a subroutine:
AskIt:
parse pull comment
say comment
say 'enter "X" to exit program'
pull continueif Continue \= "X" then returnexit
This is invoked with call AskIt "In routine that loops, counter=" counter and would display: In routine that loops counter='##enter "X" to exit programThe tester chooses to return to the code by hitting enter or exit the program with X to edit the source.Temporarily inserting return on the line following the routine label will allow you to run the code uninterrupted without removing all the calls.
I have written an edit macro for z/OS which inserts a say *routine name* after every routine label. It inserts the code with a /* comment */ containing a readily identified phrase to simplify cleanup.The audience for this would be small, so I'll not include the code here.
Hope this helps someone.
When experimenting I often use if (true) {..} or if (false) {..} to section off chunks of code I'm playing with.
The problem is that compilers these days sometimes issue a warning about unreachable code. I then have to promote my code to something like if ((10 % 2) == 0), but then some smarter compilers catch this as unreachable too.. (And so a small arms race begins..)
How do I solve this problem?
Try moving it out of the code, using pre-processor flags:
#if false
.... code which won't get run ....
#endif
Some IDEs will even collapse such un-runnable blocks for you to keep them out of the way.
Why not just use some kind of "environment variable" to control this kind of thing? Make it a reall conditional then you're not fighting the compiler.
if ( environment.MODE_EXPERIMENT) {
experimental code here
}
Personally I try pretty hard to avoid doing this kind of thing, we have SCM systems that allow us to keep old versions of code, really shouldn't need to do this too much.
This should do:
if (atoi("1")) {
}
This can also be useful to generate any kind of constant.
Almost every single language has a version of if(false) { } that a compiler/IDE won't complain about. The most common (afaik) look like the following:
/*
int i = 0;
String s = "I will never be run!";
*/
Yes, comments. Multi-line comments, to be exact. Stopping blocks of code from being run are pretty much their second main purpose (after documentation). if(true), of course, is then handled by not using them.
You're trying to re-invent the wheel here, and I have no idea why.
Most programmers will have had the experience of debugging/fixing someone else's code. Sometimes that "someone else's code" is so obfuscated it's bad enough trying to understand what it's doing.
What's the worst (most obfuscated) code you've had to debug/fix?
If you didn't throw it away and recode it from scratch, well why didn't you?
PHP OSCommerce is enough to say, it is obfuscated code...
a Java class
only static methods that manipulates DOM
8000 LOCs
long chain of methods that return null on "error": a.b().c().d().e()
very long methods (400/500 LOC each)
nested if, while, like:
if (...) {
for (...) {
if (...) {
if (...) {
while (...) {
if (...) {
cut-and-paste oriented programming
no exceptions, all exceptions are catched and "handled" using printStackTrace()
no unit tests
no documentation
I was tempted to throw away and recode... but, after 3 days of hard debugging,
I've added the magic if :-)
Spaghetti code PHP CMS system.
by default, programmers think someone else's code is obfuscated.
The worse I probably had to do was interpreting what variables i1, i2 j, k, t were in a simple method and they were not counters in 'for' loops.
In all other circumstances I guess the problem area was difficult which made the code look difficult.
I found this line in our codebase today and thought it was a nice example of sneaky obfuscation:
if (MULTICLICK_ENABLED.equals(propService.getProperty(PropertyNames.MULTICLICK_ENABLED))) {} else {
return false;
}
Just making sure I read the whole line. NO SKIMREADING.
When working on a GWT project, I would reach parts of GWT-compiled obfuscated JS code which wasn't mine.
Now good luck debugging real obfuscated code.
I can't remember the full code, but a single part of it remains burned into my memory as something I spend hours trying to understand:
do{
$tmp = shift unless shift;
$tmp;
}while($tmp);
I couldn't understand it at first, it looks so useless, then I printed out #_ for a list of arguments, a series of alternating boolean and function names, the code was used in conjunction with a library detection module that changed behaviour if a function was broken, but the code was so badly documented and made of things like that which made no sense without a complete understanding of the full code I gave up and rewrote the whole thing.
UPDATE from DVK:
And, lest someone claims this was because Perl is unreadable as opposed to coder being a golf master instead of good software developer, here's the same code in a slightly less obfuscated form (the really correct code wouldn't even HAVE alternating sub names and booleans in the first place :)
# This subroutine take a list of alternating true/false flags
# and subroutine names; and executes the named subroutines for which flag is true.
# I am also weird, otherwise I'd have simply have passed list of subroutines to execute :)
my #flags_and_sub_names_list = #_;
while ( #flags_and_sub_names_list ) {
my $flag = shift #flags_and_sub_names_list;
my $subName = shift #flags_and_sub_names_list;
next unless $flag && $subName;
&{ $subName }; # Call the named subroutine
}
I've had a case of a 300lines function performing input sanitization which missed a certain corner case. It was parsing certain situations manually using IndexOf and Substring plus a lot of inlined variables and constants (looks like the original coder didn't know anything about good practices), and no comment was provided. Throwing it away wasn't feasible due to time constraints and the fact that I didn't have the specification required so rewriting it would've meant understanding the original, but after understanding it fixing it was just quicker. I also added lots of comments, so whoever shall come after me won't feel the same pain taking a look at it...
The Perl statement:
select((select(s),$|=1)[0])
which, at the suggestion of the original author (Randal Schwartz himself, who said he disliked it but nothing else was available at the time), was replaced with something a little more understandable:
IO::Handle->autoflush
Beyond that one-liner, some of the Java JDBC libraries from IBM are obfuscated and all variables and functions are either combinations of the letter 'l' and '1' or single/double characters - very hard to track anything down until you get them all renamed. Needed to do this to track down why they worked fine in IBM's JRE but not Sun's.
If you're talking about HLL codes, once I was updating project written by a chinese and all comments were chinese (stored in ansii) and it was a horror to understand some code fragments, if you're talking about low level code there were MANY of them (obfuscated, mutated, vm-ed...).
I once had to reverse engineer a Java 1.1 framework that:
Extended event-driven SAX parser classes for every class, even those that didn't parse XML (the overridden methods were simply invoked ad hoc by other code)
Custom runtime exceptions were thrown in lieu of method invocations wherever possible. As a result, most of the business logic landed in a nested series of catch blocks.
If I had to guess, it was probably someone's "smart" idea that method invocations were expensive in Java 1.1, so throwing exceptions for non-exceptional flow control was somehow considered an optimization.
Went through about three bottles of eye drops.
I once found a time bomb that had been intentionally obfuscated.
When I had finally decoded what it was doing I mentioned it to the manager who said they knew about the time bomb but had left it in place because it was so ineffective and was interwoven with other code.
The time bomb was (presumably) supposed to go off after a certain date.
Instead, it had a bug in it so it only activated if someone was working after lunchtime on Dec 31st.
It had taken three years for that circumstance to occur since the guy who wrote the time bomb left the company.