I like refactoring
Refactoring code involves extracting an interface from a complex, large class.
class LanguageProcessor:
def concat(self, prev_text, new_text):
if self.language == 'en':
... # Concatenate logic for English
elif self.language == 'ja':
...
In my understanding, the interface should be:
Clear input/output design, minimal code, and single-responsibility simplicity.
In this case, I would do something like this:
class BaseConcatter:
# Define interface
@abstractmethod
def concat(self, prev_text: str, new_text: str):
...
class CustomConcatException(Exception):
pass
class EnglishConcatter(BaseConcatter):
...
class JapaneseConcatter(BaseConcatter):
...
class Language(Enum):
ENGLISH = auto()
JAPANESE = auto()
...
concatters = {
Language.ENGLISH: EnglishConcatter(),
Language.JAPANESE: JapaneseConcatter(),
}
Then, the original code becomes:
class LanguageProcessor:
def __init__(self):
self.concatters = concatters
def concat(self, prev_text, new_text):
if self.language not in self.concatters:
raise SomeException('Unsupported language to concat.')
result = self.concatters[self.language].concat(prev_text, new_text)
...
Design the interface, implement it, create factories, and trim conditionals. It looked good until it wasn’t.
Stupid Mistake
There is some code like this:
try:
language_processor.concat(prev_text, new_text)
except ExistingException:
# Some handling
except Exception:
# Cancel process
If you add a new exception in a concatter, like CustomConcatException, the calling code breaks because the new error bypasses the specific handler and drops into the generic path, cancelling the process. Not every concat failure should cancel everything—this actually happened.
Why did it happen?
My understanding of the interface was incomplete. It is not just input/output; it includes everything observable from outside the process. Exception handling is part of the contract, and I missed it.
Lesson Learned
An interface should define inputs, outputs, and expected exceptions; stay minimal; and keep single responsibility. When refactoring existing code, the exception contract can be the most important part.