It's not bad practice as such, but for efficiency we can do away with the need to create a Model definition item in Sitecore, and determine the Model from the View itself.
I recently wrote a blog post on this very subject as I was curious, but to summarise:
John West prototyped a pipeline processor to do exactly this back in 2014.
He proposed patching a processor into the mvc.getModel pipeline to inspect the compiled view type and return an instance of the custom Model class (should it be set).
Snippet from the processor (summarised for brevity):
public override void Process(GetModelArgs args)
{
Type compiledViewType = BuildManager.GetCompiledType(path);
Type baseType = compiledViewType.BaseType;
if (baseType == null || !baseType.IsGenericType)
{
// Log error
}
var modelType = baseType.GetGenericArguments()[0];
if (modelType == typeof(object))
{
// When no @model is set, the result is a ViewPage<object>
throw new Exception(string.Format(
"View '{0}' needs a @model directive.",
args.Rendering.RenderingItem.InnerItem["path"]));
}
args.Result = Activator.CreateInstance(modelType);
}
A couple of years later Nat Mann proceeded to run with John's idea, taking the same fundamental approach, but optimised the prototype for performance and fixed an issue for layouts without a model specified. Nat's version can be found here here.
Glass Mapper has also incorporated code into it's popular library to get the Model from the View as of release 4.0.0.4.