I have recently had to split a class into two and found raising exceptions via a new error class was key to the success of this process.
I’ve been working on Geminabox. The goal was to add the facility for Geminabox to act as a proxy for RubyGems.
At an early stage of the development, there was a requirement to split the Geminabox class into two. The problem was that this class was both handling the storage of local gems, and the HTTP requests for this service. This made it difficult to hook into Geminabox to store a new local gem, without also loading up the Sinatra component that was handling the HTTP requests.
A key to understanding the problem is to have a look at the original Geminabox#handle_incoming_gem method. This method calls further Geminabox instance methods to handle the storage of the incoming gem.
The solution was to create a new class that would handle the gem storage, and for Geminabox#handle_incoming_gem to pass the new gem to that class. The new class was called GemStore.
In the original Geminabox class, the error handling was combined into a single method that also controlled the output of an HTML error report via HTTP. That method being Geminabox#error_response. This method could be called by a number of Geminabox instance methods active in the gem storage process. The raising of errors needed to be separated from the mechanism for displaying error messages.
The result was a new error class GemStoreError. Now GemStore could raise a GemStoreError when a problem was identified. Then any process using GemStore could easily identify these errors and handle them appropriately.
With GemStore and GemStoreError in place Geminabox#handle_incoming_gem could be refactored, and other processes could use GemStore to store gems within Geminabox.