3
\$\begingroup\$

In this python program, I built a ticketing system with functionality such as keeping track of tickets sold and error handling in case there are any invalid inputs.

I need advice on my code in terms of (architecture, risks, opportunities, design) so that I can learn how I can code better & grow my skills.

TICKET_PRICE = 10
SERVICE_CHARGE = 2

tickets_remaining = 100

def calculate_price(ticket_amount):
    return (ticket_amount * TICKET_PRICE) + SERVICE_CHARGE


while tickets_remaining >= 1:
    print('There are {} tickets remaining'.format(tickets_remaining))

    # Capture the user's name and assign it to a new variable
    name = input('What is your name?: ')

    # Ask how many tickets they would like and calculate the price
    ticket_amount = input(
        '{}, How many tickets would you like?: '.format(name))
    # Expect a ValueError to happen and handle it appropriately
    try:
        ticket_amount = int(ticket_amount)
        # Raise a ValueError if the request is more tickets than there are available
        if ticket_amount > tickets_remaining:
            raise ValueError(
                'Sorry, there are only {} tickets remaining.'.format(tickets_remaining))
    except ValueError as err:
        print('Sorry, invalid input {}'.format(err))
    else:
        price = calculate_price(ticket_amount)
        print('Your total is ${} for {} tickets'.format(price, ticket_amount))

        # Prompt the user if they want to proceed Y/N
        proceed = input(
            'Would you like to proceed with your purchase? yes/no: ')
        if proceed.lower() == 'yes':

            # TODO: Gather credit card information and process it

            print('Sold!')
            tickets_remaining -= ticket_amount
        else:
            print('Thank you {}, hope to see you again soon.'.format(name))

# Notify the user when the tickets are sold out
print('Sorry, the tickets are sold out.')

‘’’

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$
  1. Overall, your code looks pretty clean and well explained;

  2. When you want to get a 'yes' or 'no' from the user I advise you to just check the character you need the user to type so that you disregard typos or excesses. So instead of if proceed.lower() == 'yes' I usually use if 'y' in proceed.lower();

  3. You used the Python-3.x tag, so I believe you are using the latest version of Python, so I would consider using f-Strings. With that, I would make the following changes:

TICKET_PRICE = 10
SERVICE_CHARGE = 2

tickets_remaining = 100


def calculate_price(ticket_amount):
    return (ticket_amount * TICKET_PRICE) + SERVICE_CHARGE


while tickets_remaining >= 1:
    print(f'There are {tickets_remaining} tickets remaining')

    # Capture the user's name and assign it to a new variable
    name = input('What is your name?: ')

    # Ask how many tickets they would like and calculate the price
    ticket_amount = input(f'{name}, How many tickets would you like?: ')
    # Expect a ValueError to happen and handle it appropriately
    try:
        ticket_amount = int(ticket_amount)
        # Raise a ValueError if the request is more tickets than there are available
        if ticket_amount > tickets_remaining:
            raise ValueError(f'Sorry, there are only {tickets_remaining} tickets remaining.')
    except ValueError as err:
        print(f'Sorry, invalid input {err}')
    else:
        price = calculate_price(ticket_amount)
        print(f'Your total is ${price} for {ticket_amount} tickets')

        # Prompt the user if they want to proceed Y/N
        proceed = input('Would you like to proceed with your purchase? yes/no: ')
        if 'y' in proceed.lower():

            # TODO: Gather credit card information and process it

            print('Sold!')
            tickets_remaining -= ticket_amount
        else:
            print(f'Thank you {name}, hope to see you again soon.')

# Notify the user when the tickets are sold out
print('Sorry, the tickets are sold out.')

As I told you, overall your code is pretty clean and I didn't see much to change, but I hope I somehow helped.

\$\endgroup\$
2
\$\begingroup\$

Just some quick remarks:

  • it's good that effort has been put into comments, but the code is so obvious that the comments do not tell us anything new. So I would instead write a more general docstring on top of the script to explain some of the business logic for example, that may not be obvious if you only see the code but lack the context
  • "yes" should probably be the default answer, so just typing enter should be equivalent to Y
  • there should be some persistence, especially if you will be taking credit card payments - which seems to be a stated purpose. I guess you will be using some database to store data ?
  • Journalization/book-keeping: I strongly recommend that you use the Python logger module, and then you can start doing stuff like: logger.info(f'Recording sale of {ticket_amount} for {price} tickets to {name}') to write events to a log file on disk (but also to other destinations such as the console if you wish). NB: the entries will be timestamped in the log file if you include the timestamp in your log formater.
  • there should be more validation of user input, for instance purchasing a negative number of tickets will not trigger an exception, but cause logic errors. A simple regular expression like ^[0-9]+$ would suffice to validate the input. Then you can ditch the except ValueError part.
  • also, a quality application should have some global exception handling. So I recommend to wrap your script in a try/catch block to handle exceptions that are not explicitly addressed in other parts of your code. And of course, log the stack trace to the log file (logger.error('the stack trace details...')). This is even more important for unattended programs, or when the program is going to be used by somebody else, and you won't be in front of the screen right when a problem occurs. It's hard to debug when you don't have a trace and have to rely on confused explanations from an end user. If on the other hand they can send you a log file, everything usually becomes clear.

PS: maybe it's just me but I find ticket_amount to be slightly confusing as a variable name - amount could be understood as the sum of money paid, so I might use something like ticket_quantity instead. And I would rename price to total_price to make it clear it's not the unit ticket price but the final amount paid by customer. Likewise, I would rename name to customer_name because the variable name is too generic. In other languages "name" would be a reserved keyword.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.