patternpythonMinor
Validating Support Tickets
Viewed 0 times
supportticketsvalidating
Problem
Being given the following code I wonder how can I make it better, without using variable valid, yet check ALL the cases and if at least one of them matches set the returned value to False
def validate_ticketer_issue(self, ticketer_issue):
"""
Validate ticket system issue for common rules
:param ticketer_issue: (str) ticket system issue key
:return: (bool) True if issue is successfuly validated
"""
valid = True
issues_not_allowed = ('Pool', 'Document', 'Declaration', 'Restriction', 'Pre-Check')
issues_not_allowed_inprod = ('Analysis', 'Test')
try:
issue = self.service.issue(ticketer_issue)
if len(issue.fields.versions) == 0: # Affects Version/s
valid = False
print('{}: Affects Version/s field is empty'.format(ticketer_issue))
if issue.fields.issuetype.name in issues_not_allowed:
valid = False
print('{}: According to working model commit is not'
' allowed to the ticket system issue types'
'{}'.format(issue['key'], issues_not_allowed))
if issue.fields.issuetype.name in issues_not_allowed_inprod:
valid = False
print('{}: According to working model commit'
' to the ticket system {} issue types'
' is not allowed in production code'.format(
issues_not_allowed_inprod, issue['key']))
if issue.fields.issuetype.name == 'Fault':
if not self.validate_fault_issue_summary(issue):
valid = False
except ticketer.exceptions.TicketerError:
valid = False
print('{}: issue does NOT exist in the ticket system!'.format(ticketer_issue))
if valid:
print('{}: OK'.format(ticketer_issue))
return validSolution
The code you show is explicit about what it does, easy to read and understand. I suppose you find the usage of the
When you encounter an error, you are actually doing two things : setting the
You could raise an exception from inside the
Also, your
Finally you could see the function as a bunch of predicates with specific error messages run one after the other.
This example might seem more scalable but for a small amount of predicates, it is probably overkill as understanding the code is not obvious, logic lives in other places, and some work has to be done to harmonize predicates and their messages.
These are the few ideas I have to improve the code so that it doesn't rely on the
valid flag error-prone in case the logic gets deeper nested, or any sort of refactoring that might forget about that flag?When you encounter an error, you are actually doing two things : setting the
valid flag to False and printing an error. One simplification would be to make a list of error messages (no valid variable), and push error messages on it. You don't print anymore, and the list of errors becomes the valid flag.def validation_function(item):
errors = []
try:
if not test1:
errors.append("Error on test 1 for item")
if not test2:
errors.append("Error on test 2 for item")
except SomeException as e:
errors.append("Exception on whatever for item")
# change the return type to list of errors
# reporting errors is responsability of caller.
return errorsYou could raise an exception from inside the
validation_function but I see it as a low level validation routine which collects errors and returns them. The caller is responsible for handling (raise, print) the returned errors if any.Also, your
validate_ticketer_issue is actually harmonizing errors : it leads its own set of tests but also catches exceptions raised by functions it calls and translates that to a boolean + error messages. The above example preserves that behaviour which is all right as long as you are very specific about the exceptions you catch.Finally you could see the function as a bunch of predicates with specific error messages run one after the other.
# List of predicates and messages. Predicates must have a
# harmonized api. Note: I'm using lambdas here but regular
# functions will work too.
PREDICATES = [
(lambda item: some_logic_here, "Error on test 1 for item"),
(lambda item: some_other_logic_here, "Error on test 2 for item")
]
def validation_function(item):
errors = []
try:
for predicate, msg in PREDICATES:
if not predicate(item):
# here you have to harmonize you messages
# so that they can be formatted using the
# same argument.
errors.append(msg.format(item=item))
except SomeException as e:
errors.append("Exception on whatever for item")
# change the return type to list of errors
# reporting errors is responsability of caller.
return errorsThis example might seem more scalable but for a small amount of predicates, it is probably overkill as understanding the code is not obvious, logic lives in other places, and some work has to be done to harmonize predicates and their messages.
These are the few ideas I have to improve the code so that it doesn't rely on the
valid flag. The second step makes it perhaps more scalable at the expense of readability.Code Snippets
def validation_function(item):
errors = []
try:
if not test1:
errors.append("Error on test 1 for item")
if not test2:
errors.append("Error on test 2 for item")
except SomeException as e:
errors.append("Exception on whatever for item")
# change the return type to list of errors
# reporting errors is responsability of caller.
return errors# List of predicates and messages. Predicates must have a
# harmonized api. Note: I'm using lambdas here but regular
# functions will work too.
PREDICATES = [
(lambda item: some_logic_here, "Error on test 1 for item"),
(lambda item: some_other_logic_here, "Error on test 2 for item")
]
def validation_function(item):
errors = []
try:
for predicate, msg in PREDICATES:
if not predicate(item):
# here you have to harmonize you messages
# so that they can be formatted using the
# same argument.
errors.append(msg.format(item=item))
except SomeException as e:
errors.append("Exception on whatever for item")
# change the return type to list of errors
# reporting errors is responsability of caller.
return errorsContext
StackExchange Code Review Q#154992, answer score: 5
Revisions (0)
No revisions yet.