Centro is right that a Module (or a NotInheritable Class with Shared members) is the closest equivalent to a C# static class. So technically, nothing is wrong with it as it's just one of VB's ways of creating this type of class. For example, you cannot say Public Shared Class Settings in VB as you cannot put the Shared keyword on a class.
On its own I wouldn't call it bad practice if a specific circumstance calls for a Module, but otherwise a Module (or other static class equivalents) likely is not the design choice you want for having loosely coupled, testable code. Additionally, while a NotInheritable Class with Shared members is more descriptive than just saying Module, there is at least one circumstance where a Module must be used instead.
When would you need to use Modules in VB.Net? If you want to take advantage of extension methods, then it's your only option since as mentioned, you cannot create a shared (static) class in VB.Net, neither can you use extensions on NotInheritable Classes. You must use a module as follows:
Imports System.Runtime.CompilerServices
Public Module StringExtensions
<Extension()> _
Public Function Remove( _
ByVal input As String, _
ByVal subStrings As String()) As String
Return String.Join("", input.Split(subStrings, StringSplitOptions.None)).Trim()
End Function
End Module
In C# you can't use modules and must use static classes as follows:
public static class StringExtensions
{
public string Remove(this string input, string[] subStrings)
{
return string.Join("", input.Split(subStrings, StringSplitOptions.None)).Trim();
}
}