• 12 hours
  • Easy

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 4/18/24

Break Down an Object-Oriented Programming Problem in Python

How to Break Down a Programming Problem

When you face a programming problem, whether it’s a problem description like in an OpenClassrooms project or user stories like in an agile workplace, you have to translate the concepts and the problem into code.

You’ll most likely refine a process for doing this throughout your career that works for you, and modify that process based on the project and the different processes and constraints.

Some developers prefer to plan, identifying each of the system elements before touching their IDE. You can identify the objects and operations that need to occur in the system, drawing diagrams (for example, UML diagrams), and taking notes.

Other developers prefer to use a more hands-on prototyping approach, where they’ll attempt to understand the problem by building it. With this approach, you have to be willing to throw out code as your design develops. You can start with one part of the problem, try different approaches, and use placeholder code and classes to model the interactions between other parts of your system.

Take a moment to consider the benefits and weaknesses of both of these approaches. Is there any way they can be used together?

Whichever process you end up using, there are a few things you need to discover.

Features

What does your program or feature need to do? What additional features may be needed in the future? How do you ensure that your code is extensible so those modifications are possible?

Objects

What objects exist in the problem space? What are the responsibilities of each of the objects? What are they used for?

Interfaces

To what extent will this code be interacting with other systems and other code? What will the interfaces - the methods, functions, and other functionality that links your program with others - look like?

With that in mind, let’s try it! Throughout your development career, you’ll be carrying out this process many times - plenty of time for refinement and the integration of new ideas and methods.

Your Turn: Break Down a Problem

You’re designing an order management system for your workplace. It will have to interface with your company’s accounting system and the inventory management system, both of which are accessible using a REST interface.

REST interfaces are a common design pattern that you’ll likely encounter a lot in the modern world. Each REST interface will define ways to respond to HTTP (web) requests sent in a certain format and provide data and perform operations based on those requests.

You’re have been provided with the following sample user stories that you’ll need to base your initial design on:

  • As a supply manager, I want to see the inventory’s items and their corresponding stock, to make informed purchasing decisions.

  • As a supply manager, I wish to send orders to suppliers to buy items, so I can ensure that the company has the stock it needs.

  • As a supply manager, I want to send my orders to our accounting software so that our suppliers will be paid on time.

  • As a treasurer, I want orders over a certain amount to require my authorization to meet regulatory requirements.

  • As a warehouse worker, I want to mark orders as arrived so I can update the inventory.

You should consider and plan a design based on:

  • The different classes that would need to be written and their responsibilities.

  • How should the system interact with the other systems mentioned; what operations will likely need to be performed, and what data needs to be sent and received?

What screens (i.e., interface pages) will need to exist for all of the above functionality?

Practice Makes Perfect

Ready to take on a more complex programming problem? Complete the following 13-step mini-project and ensure your Python skills are robust! 😎 In this lesson, we are going to use modular programming techniques to implement a useful real-world system. In particular, we will:

  • Design and implement a Python package for generating charts

  • See how changing requirements can be the downfall of a successful system

  • Discover the ways in which modular programming techniques can help you to deal with changing requirements in the best possible way

  • Learn that changing requirements can be good, because they give you the opportunity to re-think your program, resulting in more robust and well-designed code

Introducing Charter

Charter will be a Python library for generating charts. Developers will be able to use Charter to convert raw numbers into good-looking line and bar charts, which can then be saved as image files. The following is an example of the sort of chart that the Charter library will be able to generate:

A chart of wild parrot deaths produced by Charter
Charter

The Charter library will support line and bar charts. While we will keep Charter relatively simple by only supporting two types of charts, the package will be designed so that you can easily add more chart types and other charting options if you wish.

Designing Charter

When you look at a chart like the one shown in the previous step, you can identify a number of standard elements that are used by all types of charts. These elements include a title, the x and y axes, and one or more data series:

Each charter has a title, a y axis, an x axis, and data series.
Charter's key elements

To use the Charter package, a programmer would create a new chart and set the title, the x and y axes, and the data series to be displayed. The programmer would then ask Charter to generate the chart, saving the result as an image file on disk. By combining and configuring the various elements in this way, a programmer can create any chart that they may wish to generate.

Lessons Learned

Let's look back over what we have achieved in this exercise. There are several things you may notice:

  • Rather than jumping in and starting to tinker with the code, it is generally better to step back and think about the structure of the existing code base and what might need to be changed to meet the new requirements.

  • Where the new requirement involves a library or tool you haven't used before, it is worth spending some time researching the possible options, and possibly writing a simple example program to check that the library will do what you want, before you start updating your code.

  • Through the judicious use of modules and packages, the changes needed to your existing code can be kept to a minimum. In Charter, we could make use of all our existing renderer modules, with only a minor change to the source code. We only had to rewrite one function (the generate_chart() function), and add a new renderer module to simplify access to our renderers, before writing a new PDF version of each renderer. In this way, the use of modular programming techniques helped to isolate the changes to just the affected parts of the program.

  • As often happens, the resulting system is better than the one we started with. Rather than turning our program into spaghetti code, the requirement to support PDF generation resulted in a more modular and better structured library. In particular, the renderer module dealt with the complexity of rendering the various chart elements in various formats, allowing the rest of the system to simply call renderer.draw() to do the work rather than having to import and use lots of modules directly. Because of this change, we can easily add more chart elements, or more output formats, with minimal further changes to our code.

The overall lesson here is clear: rather than resist changes to your requirements, embrace them. The end result is a better system—more robust, more expandable, and often better organized. Provided, of course, that you do it right.

In this lesson, we used modular programming techniques to implement a hypothetical chart-generation package called Charter. We saw how charts are made up of standard elements, and how this organization can be translated into program code. After successfully creating a working chart-generation library that renders charts as bitmapped images, we saw how a fundamental change in requirements can seem to be a problem at first, but is actually an opportunity to refactor and improve your code.

Following through with this hypothetical example, we refactored the Charter library to handle PDF formatted charts. In doing so, we learned that using modular techniques to respond to a major change in requirements can help to isolate the changes that need to be made, and that refactoring our code often results in a system that is better organized, more expandable and more robust than what we started with.

Let’s Recap!

  • When faced with a programming problem, you need to break the problem down into smaller parts.

  • You can consider the desired features, objects in the domain, and other code it has to interface with in the design.

  • Learning to break down a problem is a skill that is honed through repetition and experience.

Covering design and structure leaves us with just one more thing to do: handle errors. In the next - and last - chapter you’ll learn how to handle and create exceptions. 

Example of certificate of achievement
Example of certificate of achievement