Last Revision — April 19, 2022
2 Min Read
---
Couplers
Responsibility
Within a Class
- Null Check (causes)
- Required Setup or Teardown Code (causes)
Marcel Jerzyk in thesis (2022): "Code Smells: A Comprehensive Online Catalog and Taxonomy"
The Afraid To Fail is a Code Smell name inspired by the common fear (at least among students [1]) of failure, which is professionally called Atychiphobia [48] - being scared of failure.
I am referencing it here because the fear of admitting failure (that something went wrong) is a common, relatable, psychological trait, and facing that fear would benefit everyone. It is not a good idea to hope that maybe someone will get away with it. Undoubtedly, maybe even more often than not, that would be the case, but the more things stack up on that lack of honesty, the harder it will eventually hit if it ever gets discovered.
In programming, this behavior will clutter the code because, after a method or function call, additional code is required to check whether some status code is valid, a boolean flag is marked, or the returned value is not None
. And all of that is outside of the method scope.
If it is expected that a method might fail, then it should fail, either by throwing an Exception
or, if not - it should return a special case None
/Null
type object of the desired class (following the Null Object Pattern), not null itself. For example, if an expected object cannot be received or created, and instead of some status indicator is sent back (which has to be checked after the method is completed), the smells it generates would be Afraid to Fail as well as Teardown Code Code Smell. Instead, following the Fail Fast Principle, the code should throw an error.
Require additional if
checks for return status or null
checks.
Creates artificial coupling with the method caller.
In system design, the Fail Fast concept is about reporting immediately when any condition is likely to indicate failure.
Returning Status Code, which has to be checked eventually whether it succeeded
def create_foo() -> dict:
response = requests.get('https://api.github.com/events')
if response.status_code != requests.codes.ok:
return {'status_code': response.status_code, 'foo': None}
return {
'status_code': response.status_code,
'foo': Foo(**response.json())
}
foo_response: dict = create_foo()
if foo['status_code'] != requests.codes.ok:
foo: Foo = foo_response['foo']
...
Immediately throw an exception if the expected result from the function will not be achieved
def create_foo() -> Foo:
response = requests.get('https://api.github.com/events')
if response.status_code != requests.codes.ok:
raise Exception('Something went wrong')
return Foo(**response.json())
foo: Foo = create_foo()
...