1

I've been told to write a simple program that generates coupon codes, which should offer more than two algorithms (any two) and that the algorithm and the number of codes generated should be read from a config file. Also I've been told that the solution would involve using a known design pattern and that I should look for what pattern is.

I've come up with two solutions for this, but I don't think I've found a proper OOP design pattern that fits for the problem, since objects are data with methods that operate over that data, and in this problem there is little data to operate over, it's more a function (functional?) problem to my naive eyes. Here are the two, one is basically executing the proper static method for the algorithm in the config file and the other returns a reference to a function. Both generate the numbers and print them to the screen.

First method:

class CouponGenerator:
    SEQUENTIAL_NUMBERS = "sequentialNumbers"
    FIBONACCI_NUMBERS = "fibonacciNumbers"
    ALPHANUMERIC_SEQUENCE = "alphanumericSequence"
    quantity = 0
    algorithm = ""

    def __init__(self, quantity, algorithm):
        self.quantity = quantity
        self.algorithm = algorithm

    def generateCouponList(self):
        numbers = list()

        if self.algorithm == self.SEQUENTIAL_NUMBERS:
            numbers = CouponGenerator.generateSequentialNumbers(self.quantity)
        elif self.algorithm == self.FIBONACCI_NUMBERS:
            numbers = CouponGenerator.generateFibonacciSequence(self.quantity)

        for number in numbers:
            print number

    @staticmethod
    def getCouponGenerator(configFile):
        cfile = open(configFile)
        config = cfile.read()
        jsonconfig = json.loads(config)
        cg = CouponGenerator(jsonconfig['quantity'], jsonconfig['algorithm'])
        return cg

    @staticmethod
    def generateSequentialNumbers(quantity):
        numbers = list()
        for n in range(1, quantity+1):
            zeroes = 6-len(str(n))
            numbers.append(zeroes*"0"+str(n))

        return numbers

    @staticmethod
    def generateFibonacciSequence(quantity):
        def fib(n):
            a, b = 0, 1
            for _ in xrange(n):
                a, b = b, a + b
            return a

        numbers = list()
        for n in range(1, quantity+1):
            number = fib(n)
            zeros = 6-len(str(number))
            numbers.append(zeros*"0"+str(number))
        return numbers

if __name__ == "__main__":
    generator = CouponGenerator.getCouponGenerator("config")
    generator.generateCouponList()

Second solution:

class CouponGenerator:
    @staticmethod
    def getCouponGenerator(algorithm):
        def generateSequentialNumbers(quantity):
            numbers = list()
            for n in range(1, quantity+1):
                zeroes = 6-len(str(n))
                numbers.append(zeroes*"0"+str(n))
            return numbers


        def generateFibonacciSequence(quantity):
            def fib(n):
                a, b = 0, 1
                for _ in xrange(n):
                    a, b = b, a + b
                return a

            numbers = list()
            for n in range(1, quantity+1):
                number = fib(n)
                zeros = 6-len(str(number))
                numbers.append(zeros*"0"+str(number))
            return numbers

        generators = {"sequentialNumbers": generateSequentialNumbers,
                      "fibonacciNumbers": generateFibonacciSequence}

        return generators[algorithm]

class CouponGeneratorApp:
    configFile = "config"
    def __init__(self):
        cfile = open(self.configFile)
        config = cfile.read()
        self.jsonconfig = json.loads(config)
        self.generateCouponCodes()

    def generateCouponCodes(self):
        generator = CouponGenerator.getCouponGenerator(self.jsonconfig["algorithm"])
        numbers = generator(self.jsonconfig["quantity"])
        for n in numbers:
            print n

if __name__ == "__main__":
    app = CouponGeneratorApp()
Adrián Pérez
  • 2,186
  • 4
  • 21
  • 33
  • Why? there are design patterns using static methods. Like static factories in java. – Adrián Pérez Feb 27 '14 at 01:24
  • 2
    [Python is not Java.](http://dirtsimple.org/2004/12/python-is-not-java.html) – Ignacio Vazquez-Abrams Feb 27 '14 at 01:26
  • Could you explain yourself better please? I don't find exactly what you are trying to tell me from that webpage. – Adrián Pérez Feb 27 '14 at 01:55
  • @AdriánPérez They're just being inappropriate with their comments. I agree with you, static methods are valid for OOP. I don't, on the other hand, know how to answer your question. – Adam Feb 27 '14 at 02:47
  • I think the design pattern you're looking for is a [class factory](http://stackoverflow.com/questions/2526879/what-exactly-is-a-class-factory/2949205#2949205). – martineau Feb 27 '14 at 04:37
  • 1
    Do your requirements demand you use a class? If you just need a function... just use a function. Regarding design patterns, there are a lot - do you have no other guidance than 'design pattern'? If this is homework, also please note that on the question. – KobeJohn Feb 27 '14 at 04:40

1 Answers1

0

If you want to make it a little more object oriented I suggest you use some kind of strategy pattern, that means, use a class per generation algorithm (which should have a common interface) and specify that CouponGenrator use an object which implements this interface to do whatever it has to do. This is theory and making interface and everything in your case might be a little to much.

http://en.wikipedia.org/wiki/Strategy_pattern

you could try something like :

class SequentialGenerator(Object):
    def implementation():
        ...

class FibonacciGenerator(Object):
    def implementation():
        ...

class CouponGenerator(Object):
    def set_generator(generator):
        # set self.generator to either an instance 
        # of FibonacciGenerator or SequentialGenerator

    def generate_coupon_code():
        # at some point calls self.generator.implementation()
OAnt
  • 131
  • 1
  • 4