When should you define your own exceptions? Any rules of thumb?
I'm writing an application that runs on a computer and listens for
requests to start, kill, and view log files for other applications on
that computer. Say I get a request to start an application on that
computer and the requested executable doesn't exist. Should I throw a
custom exception then? Or, say an application dies unexpectedly.
What should I use for an exception then?
class Application
...
def start
raise "No executable given!" if not @executable
if @pid = fork
Process.detach @pid @status = :running
else @options.each do |option_name, option_value|
ENV[option_name] = option_value
end
args = @arguments.join " "
exec "#{ basedir }/#{ version }/#{ executable } #{ args }"
end
end
...
end
So, if there's no valid executable, then the exec call will fail.
What's the best way of transmitting that information to the rest of
the system?
···
On 8/30/05, Joe Van Dyk <joevandyk@gmail.com> wrote:
Hi,
When should you define your own exceptions? Any rules of thumb?
I'm writing an application that runs on a computer and listens for
requests to start, kill, and view log files for other applications on
that computer. Say I get a request to start an application on that
computer and the requested executable doesn't exist. Should I throw a
custom exception then? Or, say an application dies unexpectedly.
What should I use for an exception then?
When should you define your own exceptions? Any rules of thumb?
I define custom exceptions when I need to differentiate them from the built-in exceptions.
I'm writing an application that runs on a computer and listens for
requests to start, kill, and view log files for other applications on
that computer. Say I get a request to start an application on that
computer and the requested executable doesn't exist. Should I throw a
custom exception then? Or, say an application dies unexpectedly.
What should I use for an exception then?
Sometimes an exception with a message is enough. Other times I need to know the difference between two RuntimeErrors with different messages.
I create my own exceptions for the second case because rescue FooError is easier than reading exception messages.
def test_start_bad_application
a = Application.new invalid_application_executable
assert_raise(RuntimeError) { a.start }
assert !a.running?
assert_equal :failed, a.status
end
But since it forks into a new process, I don't catch the exception. I
could check to see if the executable exists (and is executable) before
going into the fork, and if it's not valid, throw an exception. Is
that my best bet?
···
On 8/30/05, Joe Van Dyk <joevandyk@gmail.com> wrote:
On 8/30/05, Joe Van Dyk <joevandyk@gmail.com> wrote:
> Hi,
>
> When should you define your own exceptions? Any rules of thumb?
>
> I'm writing an application that runs on a computer and listens for
> requests to start, kill, and view log files for other applications on
> that computer. Say I get a request to start an application on that
> computer and the requested executable doesn't exist. Should I throw a
> custom exception then? Or, say an application dies unexpectedly.
> What should I use for an exception then?
The start function follows:
class Application
...
def start
raise "No executable given!" if not @executable
if @pid = fork
Process.detach @pid @status = :running
else @options.each do |option_name, option_value|
ENV[option_name] = option_value
end
args = @arguments.join " "
exec "#{ basedir }/#{ version }/#{ executable } #{ args }"
end
end
...
end
So, if there's no valid executable, then the exec call will fail.
What's the best way of transmitting that information to the rest of
the system?
Should the custom exception be in its own class? Or in a module?
Say I have the following class
class NodeManager
def start_application args
end
end
There are a few different ways start_application could fail:
- bad arguments
- user attempted to start the same application twice (which is an
error for us)
- not enough resources available
I want to distinguish between those different reasons. So, would I
want to have something like this:
module JoesExceptions # figure out some name
class BadArgumentsForApplication < Exception
end
class ApplicationStartedTwice < Exception
end
class NotEnoughResourcesForApplication < Exception
end
end
And then, in start_application:
def start_application args
# if arguments are bad
raise BadArgumentsForApplication
# and so on
end
···
On 8/30/05, Eric Hodel <drbrain@segment7.net> wrote:
On 30 Aug 2005, at 10:52, Joe Van Dyk wrote:
> When should you define your own exceptions? Any rules of thumb?
I define custom exceptions when I need to differentiate them from the
built-in exceptions.
> I'm writing an application that runs on a computer and listens for
> requests to start, kill, and view log files for other applications on
> that computer. Say I get a request to start an application on that
> computer and the requested executable doesn't exist. Should I throw a
> custom exception then? Or, say an application dies unexpectedly.
> What should I use for an exception then?
Sometimes an exception with a message is enough. Other times I need
to know the difference between two RuntimeErrors with different
messages.
I create my own exceptions for the second case because rescue
FooError is easier than reading exception messages.
When should you define your own exceptions? Any rules of thumb?
I'm writing an application that runs on a computer and listens for
requests to start, kill, and view log files for other applications
on that computer. Say I get a request to start an application on
that computer and the requested executable doesn't exist. Should I
throw a custom exception then? Or, say an application dies
unexpectedly. What should I use for an exception then?
I'd go with Eric's rule of thumb. It's not an exact science but you there
is a minimal criterium: if you need to catch this exception separately
from others you should introduce a new exception type.
Btw, here's a nice short script to print a class hierarchy of all
exceptions:
require 'pp'
tree = (cr = lambda {|h,k| h[k] = Hash.new &cr})[{},nil]
ObjectSpace.each_object(Class) {|cl| if cl.ancestors.include? Exception
then cl.ancestors.reverse.inject(tree){|tr,cl| tr[cl]} end}
pp tree
The start function follows:
class Application
...
def start
raise "No executable given!" if not @executable
if @pid = fork
Process.detach @pid @status = :running
else @options.each do |option_name, option_value|
ENV[option_name] = option_value
end
args = @arguments.join " "
exec "#{ basedir }/#{ version }/#{ executable } #{ args }"
end
end
...
end
So, if there's no valid executable, then the exec call will fail.
What's the best way of transmitting that information to the rest of
the system?
Eeek. So, I was trying to do a test like:
def test_start_bad_application
a = Application.new invalid_application_executable
assert_raise(RuntimeError) { a.start }
assert !a.running?
assert_equal :failed, a.status
end
But since it forks into a new process, I don't catch the exception. I
could check to see if the executable exists (and is executable) before
going into the fork, and if it's not valid, throw an exception. Is
that my best bet?
I guess so.
Kind regards
robert
···
On 8/30/05, Joe Van Dyk <joevandyk@gmail.com> wrote:
On 8/30/05, Joe Van Dyk <joevandyk@gmail.com> wrote:
>
> > When should you define your own exceptions? Any rules of thumb?
>
> I define custom exceptions when I need to differentiate them from the
> built-in exceptions.
>
> > I'm writing an application that runs on a computer and listens for
> > requests to start, kill, and view log files for other applications on
> > that computer. Say I get a request to start an application on that
> > computer and the requested executable doesn't exist. Should I throw a
> > custom exception then? Or, say an application dies unexpectedly.
> > What should I use for an exception then?
>
> Sometimes an exception with a message is enough. Other times I need
> to know the difference between two RuntimeErrors with different
> messages.
>
> I create my own exceptions for the second case because rescue
> FooError is easier than reading exception messages.
Should the custom exception be in its own class? Or in a module?
Say I have the following class
class NodeManager
def start_application args
end
end
There are a few different ways start_application could fail:
- bad arguments
- user attempted to start the same application twice (which is an
error for us)
- not enough resources available
I want to distinguish between those different reasons. So, would I
want to have something like this:
module JoesExceptions # figure out some name
class BadArgumentsForApplication < Exception
end
class ApplicationStartedTwice < Exception
end
class NotEnoughResourcesForApplication < Exception
end
end
And then, in start_application:
def start_application args
# if arguments are bad
raise BadArgumentsForApplication
I guess that would be:
raise JoesApplication::BadArgumentsForApplication
···
On 9/1/05, Joe Van Dyk <joevandyk@gmail.com> wrote:
On 8/30/05, Eric Hodel <drbrain@segment7.net> wrote:
> On 30 Aug 2005, at 10:52, Joe Van Dyk wrote: