The rule of thumb is that you should ask yourself "Who should deal with the problem logically?" and stick to that.
The important thing is to remember that when you write a piece of code you in fact write a contract describing of how bits and pieces of code interact. For example in your case when you create a MyConstructor instance why would it fail? What promise is made when it is generated? Most importantly, who should deal with it failing?
Some examples
Let's say that for example we have a class Car
and instances of Car
have a method drive(x)
.
When you call drive(x)
the Car
moves x
places to the right.
The action drive(x)
might fail, for example if the Car
is already on the edge of the screen, or Car
has no fuel.
We just defined drive
as "the Car moves x places to the right" which means that the car expects to be able to complete the drive action and being unable to complete it is logically an exception. In this case it is quite obvious that the one handling the exception is the caller of drive and not the car itself since it wouldn't have to know what environment it is driving on. Even better, the caller should not attempt to drive the car off the edge or without fuel any way.
In another case
Let's say that in the same example Environment
is a class that contains cars and it has a moveCars()
method that moves all the cars in the environment according to some inner contained logic. Environment
is used by a program that expects it to contain all the movement logic. We use some algorithm in moveCars()
that is supposed to assure us that cars do not collide.
We might have some edge case we did not think of in our moveCars()
method, or one that is not supposed to happen due to some assumption, however the user to environment expects it to contain all the move logic which means when an exception occurs it should deal with it itself.
So, what is the general strategy?
You should handle exceptions based on the responsibility the component running the code has.