Input validation, and any abstraction that smells like a framework or library make great code folds for abstraction.
The question is all about cost. Does a single layer abstraction, at the boundaries, with clear inputs and outputs have much of a cost?
I don't think so.
Does forcing vat calculation into a new class far away from the widget price class have a cost? I think so, the cost is having the same concern separated for no material gain other than perhaps reducing one form of duplication for the cost of creating another.
You may not think that input validation at the boundary has a cost, but the fact is that the "typical" Ruby on Rails application is happy to just pass controller params along to the model layer unchanged and unvalidated (there is a security layer that allows you to whitelist which parameters you want to forward, but nothing more than that). Validation is supposed to happen in the model layer. I think this is horrible design, but it's unfortunately a strong convention and breaking conventions also has associated costs. By contrast, if you write your application in e.g. Spring Boot you typically have validation at the controller level built in, so yes, in that case, it's easy to do the right thing.
I think you're right that it may not be necessary to extract "calculate_vat" into another class. It just really depends: if the VAT code is so complex that it should be properly unit tested, I think it deserves its own class. If it's fairly straightforward and only used inside of a single other price calculation class, then yeah, it can remain a private method or so.
But I don't think this is a question of whether to abstract or not, rather about what the right level of cohesion and coupling is for a given situation.
Input validation, and any abstraction that smells like a framework or library make great code folds for abstraction.
The question is all about cost. Does a single layer abstraction, at the boundaries, with clear inputs and outputs have much of a cost?
I don't think so.
Does forcing vat calculation into a new class far away from the widget price class have a cost? I think so, the cost is having the same concern separated for no material gain other than perhaps reducing one form of duplication for the cost of creating another.