2

I am writing an application in python. The part I am little confused about is providing a little structure to my code.

This is the basic requirement of my web application.

I have these different end points:

  1. GET /reports/daywise.
  2. GET /reports/bulk_report_between_date_range.
  3. GET /reports/breakdown_by_age.

For each of these endpoints, I have defined a controller (a class which handles the computation of result)

My current design is as follows: I have a base class defined ReportBuilder, and it has some setter methods like

  1. setDateRange()
  2. setKeys()
  3. setQuery()
  4. Execute()

Now for each controller, I inherit from the above base class and I override methods if required.

class ControllerDayWise(ReportBuilder):
    #..........
class ControllerBulkReport(ReportBuilder):
    #..........
class ControllerBreakdownByAge(ReportBuilder):
    #..........

The problem with above design is that I have to use setter methods in some specific order like I have to call setQuery() before setDates(), as query will obviously have dates in it.

While this works, I know there has to be a better way to structure my application. So while searching about it, I found using interfaces in python zope.interface.

The idea is that I will create an IReportBUilder interface and the controllers will implement it. Only with this, all the attributes and methods have to be redefined in all the controllers.

Any suggestions on pros/cons of each method that I have considered above? How should I approach this?

2 Answers 2

4

I think you're fundamentally misrepresenting the relationship between your classes. You're attempting to define a controller as a type of report builder, when in fact the responsibility of a controller (in the context of an MVC type framework) is to marshall a request into other areas of your code base.

This simplified example doesnt really highlight the problem (your controller is returning reports, it could be thought of as a report builder), but think of all the other things your controller has to do (logging, security management etc.). Your current approach would quickly break down if you tried to represent all of these activities with an inheritance relationship.

A better model would be to accept the request builder as a dependency of your controller. Depending on how expensive the report builder is to create, you can either create each controller with a single instance, or provide some sort of factory, so you can create a new report builder every time the controller method is called.

This way, your controller methods can be responsible for acquiring all of the necessary parameters for each report, and can then call the methods on the report builder in the correct order.

Some areas you might want to read up on that cover this area are:


Python is not really my forte, and the exact method for doing this will depend on the framework youre using, but an example controller might look like this:

class ExampleController:
    def __init__(self, report_builder_factory):
        # report builder factory could be either a function or an instance of a class
        self.report_builder_factory = report_builder_factory

    def get_daterange_report(self, start, end):
        report = self.report_builder_factory().set_date_range(start, end).execute()
        return report # Wrap this in whatever your framework provides for successful responses

This approach also makes testing easier. You can test the controllers by providing a fake implementation of the report builder, and you can test the report builder without needing to worry about any controller requirements

2
  • 1
    thankyou for the response, can you please give an example with pueudocode so that I can understand clearly.thankyou
    – anekix
    May 21, 2018 at 10:34
  • I reread your answer multiple time and it makes sense but still, some doubts.what is report_builder_factory() what should go in there?
    – anekix
    May 25, 2018 at 7:48
2

What you looking for is a Step Builder pattern to enforce methods in a certain order. However I would argue you want to do all that inside the controller. You can have a report builder factory implementing the step builder pattern and instantiate the factory based on requirement inside the controller. More on step builder pattern: https://stackoverflow.com/questions/17256627/how-to-enforce-sequence-in-function-calls

Your Answer

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

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