Why is System.out.println bad? [closed] - pmd

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
When i run my PMD plugin they say System.out.println has been used. why is System.out.println bad to use and is it a defect when using PMD plugin? and what is the alternative way of over coming this?

A logger can be turned ON/OFF using a configuration but System.out.println cannot be. Importantly loggers provide different levels of logging and again can be controlled through a configuration file.
Also using loggers you can configure rotation, purging etc but cannot do the same for sysout. This is useful especially in a production environment, executing a lot of code, and generating a lot of logging.

System.out.println() is considered bad practice for Logging.
Because of
No ability to turn it (ON/OFF)
No ability to set output levels (TRACE, DEBUG, INFO, WARN, ERROR),
without having to recompile your code
Another disadvantage is that the standard output of a program can be redirected, for instance and it's not always clear where the output is actually going, for instance if you do this:
java SomeClass > someFile
In this case the use of a logging API will help you.
But there are situations where you genuinely want to print something to the standard output too, for those occasions there is java.io.Console, which cannot be redirected, so if you're running a command line java program, it gives you confidence that the users are seeing the messages intended to them.

System.out.println..
are usually intended for debugging purposes and can remain in the
codebase even in production code. By using a logger one can
enable/disable this behaviour at will (and by priority) and avoid
clogging the Standard out log.
(from SourceMeter Java user guide under "Java Logging Rules")
Import needed (.jar)
Logger site
Example:
import org.apache.log4j.Logger;
class Foo{
private static final Logger LOG = Logger.getLogger(Foo.class);
public void testA () {
System.out.println("Entering test");
// Better use this
LOG.info("Entering test");
}
}

Printing excessive amounts of into to System.out can become a performance bottleneck because it is synchronized, code from PrintStream:
public void println(float x) {
synchronized (this) {
print(x);
newLine();
}
}

This is because, PMD defines a java logging rule named SystemPrintln which detects System.out.println in the code and consider as a defect.
Since: PMD 2.1
System.(out|err).print is used, consider using a logger.
This rule is defined by the following XPath expression:
//Name[
starts-with(#Image, 'System.out.print')
or
starts-with(#Image, 'System.err.print')
]
And you should be able to modify above XPath expression to override the behavior( I am not sure though)
Below link should give you more insight,
http://pmd.sourceforge.net/pmd-4.2.6/rules/logging-java.html

Related

DotNetFiddle or similar for ClearScript

[I realise this is slighly off-topic for SO but I am asking this as I want to raise a couple of questions around ClearScript and I want to be able to include fiddles to make life easier.]
Is there a usable dot net playground (for example DotNetFiddle) that I can use for some fundamental learning of ClearScript, and what is a minimal bare-bones config. Ideally I would like to be able to get a link to a known-good fiddle that I can fork from. I searched for ClearScript fiddle but the few I found were incomplete or non functional. I am looking for console output only.
I tried this fiddle https://dotnetfiddle.net/rpd5le# but I do not know which Microsoft.Clearscript to reference and keep getting errors such as
Run-time exception (line 8): Inheritance security rules violated while
overriding member:
'Microsoft.ClearScript.HostItem.GetInterface(System.Guid ByRef, IntPtr
ByRef)'. Security accessibility of the overriding method must match
the security accessibility of the method being overridden.
This is the simple code I have to date:
using System;
using Microsoft.ClearScript.V8;
public class Program
{
public static void Main()
{
V8ScriptEngine engine = new V8ScriptEngine();
engine.AddHostType(typeof(Console));
Console.WriteLine("Hello from C#");
engine.Execute(#"
Console.WriteLine('Hello from Javascript');
");
}
}

Warning CS7022 - The entry point of the program is global code; ignoring 'Program.Main(string[])' entry point

so I have an issue where I have this warning in my Error List:
Severity Code Description Project File Line Suppression State
Warning CS7022 The entry point of the program is global code; ignoring 'Program.Main(string[])' entry point. Project DirectoryToProject 23 Active
This is essentially where its throwing
namespace MyProgram
{
class Program
{
static async Task Main(string[] args) => await new Program.MainAsync();
}
static async Task MainAsync()
{.. do stuff.. }
}
That is the line of code that is causing the error. I've tried playing around with the Main class, I did have it with the return type void and had my GetAwaiter and GetResult method called on the MainAsync method.
I've tried researching the error but I've had no luck, so hopefully, this thread will help a few others...
I am currently running on C# 9.0
Visual Studio 2019 Build Version: 16.8.30717.126
EDIT: Forgot to show that the MainAsync was in the file... (Sorry) Im trying to limit the amount of methods I show as 95% of them aren't useful the to question... But the issue is that although my application compiles, when executing my program it quits instantly as if it doesn't know where to start...
EDIT 2:
Thanks to Hans Passant -
If anyone experiences something like this try what he mentioned:
"This is a rather awful C# v9 feature. Project > Properties > Build tab, Advanced button > Language version = 7.3 You should now get a decent error message from the code you didn't know you had to post".
Essentially upon changing back to C# 8.0 I saw it was a different file hidden away causing the issue.
Starting with net5.0, I've found that this error can be caused by having stray semicolons above the namespace keyword. Whether this is a bug or intended behavior is beyond me, however make sure you don't have any standalone semicolons as such:
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
; // This will cause CS7022
namespace Tomoe.Commands.Public
Be sure to check all your files and not just Program.cs
EDIT: Apparently this is intended behavior, see https://github.com/dotnet/roslyn/issues/53472.
TL;DR, semicolons above namespaces are interpreted as top level statements. Because nothing is being called in said statement, the program exits. This is the same as doing
static void Main() {
;
}
in your Program.cs. While I do feel some change should be made, the design decision behind this is quite logical and entirely understandable.
EDIT 2: According to jcouv on Github, this is now becoming an error instead of a warning. Hopefully, this "bug" shall harass us no more!
This can happen if a file (any file) in the project has global code, that's to say statements outside of a class.
As mentioned by others, this is caused by a new C# 9 feature that is called "Top-level statements". This Feature enables you to write statements in the global context and the compiler will create it's own Main() based on that.
In my case I had a semicolon after my using statements in any of my files. As far as I know Visual Studio or the compiler don't give you any option to find this "entry-point" without changing any settings as descripted by others in this thread.
My solution was to just create another "Top-level statement entry point" in my project. Due to the fact that there is only one allowed the compiler complains about that.
I just added a semicolon directly after the using statements in my Program.cs. Because this file is one of the first that are processed by the compiler any other file that contains a "Top-level statement" will cause an error.
I've also seen this compiler error in the following scenario. You've written your code with top-level statements. Later, you decide to absorb that logic into a Main() method. (Maybe you find you now need to return an async Task, or you need to modify it to meet a company coding standard, for example.) Even though the following code block will compile (in VS2022 at least), it generates the error in question with a green squiggly beneath Main:
static void Main()
{
Console.WriteLine("Inside the Main() method");
//Do some other work here
}
Where's the issue? The method declaration is correct, and it will run, but even when this is the only code in the Program.cs file, and even when no other entry point is specified in the project/solution settings, we do not get the expected output:
Even the Microsoft documentation isn't much help in this case, because it pretty much repeats in more detail what the error is saying.
What's missing is the Program class definition. Without it, the compiler is still looking for a top-level statement - which it finds, namely static void. Then the next thing it finds is the Main() method declaration, but it finds this after the (unintended) top-level statement static void. Hence, the error sorta makes sense now.
The fix is to wrap the above code in a Program class:
class Program
{
static void Main()
{
Console.WriteLine("Inside the Main() method");
}
}
And now we get the expected output:

Compile error when setting class in VBA [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Improve this question
I copied code from here but I'm getting an error when trying to run the code.
The problem would be in:
Public NextItem As New queueItem
and the error message is:
user-defined type not defined
Is my VBA version not right to do this or am I doing something wrong?
You probably mean this link? The one you provided has the alternative implementation (with arrays, not with references).
I got it to work for me. Steps:
Right click on the VBA project file name, and go to Insert-> Class Module:
Click F4. The Properties window appears. Then go to the class Name and change it to Queue:
Copy and Paste the Queue Class code you found at the web site. Repeat the previous and this step for the QueueItem class (i.e., insert a Class Module, name it QueueItem and copy the code inside that class module).
This time, insert a Module using the same process (not a Class Module, but rather a simple Module). You do not need to give your module a name, Module1 will be OK.
Copy the Sub TestQueue() inside the module and run it. It should work. If you use Option Explicit on your module, you will get an error that element is undefined. So we need to define it: Dim element as Variant, under the first few Dim statements of the subroutine. Then it should run.
The above worked for me, let me know if I can be more precise, or send the file to you.

Does Scala have "macro" definitions ready to use -- like LINE, FILE?

When you get a stack trace from exception you get files and line numbers. I need something like this for my reporting, so I could get to the cause very fast.
I am looking in particular for LINE and FILE macro. Is there anything like this in Scala?
There is no such macro neither in Scala nor in Java. Of course the line number information is stored in the bytecode (also for debugging purposes) but there is no API to obtain it.
Stack traces with class names and line numbers are generated via native Throwable.fillInStackTrace(). Logging libraries might also use Thread.getStackTrace().
In both cases it boils down to parse stack trace and find our current location. Note that generating stack trace is time-consuming and should be avoided.
The sourcecode library is based on macros and provides metadata at compile-time.
Example (taken from their page):
object Main extends App {
def log(message: String)(implicit line: sourcecode.Line, file: sourcecode.File) =
println(s"${file.value}:${line.value} $message")
log("foo")
}
This will print:
/Users/jhoffmann/Development/sourcecode/src/main/scala/Main.scala:5 foo
You can use the implicits anywhere in your code.
The is a project to provide a macro capability in Scala.
Perhaps you could approach the project team to discuss what you need

Logging within utility classes

I want to adopt logging within several utility classes, e. g. DBI. What is the best practice to do it with Log::Log4perl?
I think it is OK to subclass DBI (say, MyDBI) and override some methods there to make them do the logging. But there's a problem with categories. If you create a logger with
Log::Log4perl->get_logger(ref $self || $self)
then all log entries belong to MyDBI and it would be hard to filter them. So it seems better to me to pass a logger to MyDBI from the calling module (say, MyModule), so that category would be semantically right. The first question, is it OK in general? I mean, are there any hidden reefs regarding such approach?
The second question, how to pass the logger to MyDBI? I have an idea to declare a global variable, e. g. $MyDBI::logger and set in the calling method:
local $MyDBI::logger = Log::Log4perl->get_logger(ref $self || $self);
There's a traditional dislike for global variables. Can you think of a better way?
EDIT: Of course, the best code is no code. caller would suffice, if it took inheritance into account.
The third question, is it possible to log into both categories, MyDBI and MyModule, with Log::Log4perl, if they are hierarchically unrelated?
I would strongly encourage you to to log independently on the caller in a separate logger either per function or per module, so that you can run your module independently of log4perl used in your caller.
Each module will create its own logger with Log::Log4perl->get_logger("module name").If the caller does not create any appender, the program will simply not log anything and the log4perl in the modules will be ignored from a functional stand point. Log4Perl implements a singleton pattern for creating a logger, which is similar to a global variable.
Your Logging should be fine-grained as possible and as a rule of thumb I log in debug any input parameter and any result of a function/method. If really necessary, you can also use the stack trace to find out the caller which has lead to the error condition. Adding it into the parameters does just add additional complexity.
The following recipes might give you some more ideas about the flexibility on the configuration side of log4perl.Log4Perl Recipes The whole idea for me is to keep the code unchanged and change the logging configuration depending on my actual logging/bug tracing requirements (which might change in the future). To keep the code unchanged if possible is even more important with modules as you want to avoid testing all calling programs.
To answer your questions in brief.
1.) Each module should have its own logger
2.) Thus do not add the loggers into the interface
3.) Log4Perl will log on all levels depending on your appender configuration. This way you control what you will see not see - normal level will usually be INFO and specific modules might be in debug. In bad cases the Pattern layout will allow you to add the stack trace into the logging purely with configuration.