Problem Solving#

Learning Objectives#

  • Understand the importance of clearly defining requirements before starting a project

  • Decompose a large problem into smaller, manageable tasks

  • Plan the structure of a codebase to ensure scalability and maintainability

  • Choose appropriate data representations to enhance performance and efficiency

  • Select suitable tools and technologies for a project, balancing familiarity and suitability

  • Design software with future changes and collaboration in mind

  • Apply best practices for collaborative development to improve problem-solving and code quality

Exercise#

The following narrative describes how two researchers, Sam and Charlie, have got started on their research problem. After reading the passage, given what we have discussed so far, what are some of the potential processes they could have followed to stop them from having to rewrite the code?

Sam wants to train a model to predict whether someone has a certain medical condition - they have clinical data, including diagnoses of the condition. Sam is collaborating with Charlie, and they have a high-level chat about the project, discussing what they would like to get out of the model. Sam is keen to get started so fires up the computer and begins writing code. After some time, Charlie asks Sam to share the uncertainties of the current model predictions - Sam does not have this information. Together, Sam and Charlie make changes to the code. To enable uncertainties to be calculated, they end up having to rewrite a significant amount of the code. Following this, they are stuck with what to do next.

Hint

  • What could Sam and Charlie have discussed at the start of the project?

  • What could Sam have done before starting to write code?

  • How could they have avoided rewriting lots of code?

Fundamentals#

Understanding Requirements#

Before beginning any software project, it’s essential to clearly understand and define the requirements. This understanding shapes the software’s design and functionality.

  • Functional Requirements: Define what the software should do. For example, a functional requirement could be that the software provides the uncertainty of a prediction.

  • Non-Functional Requirements: Specify how the software should behave. For example, a non-functional requirement might stipulate that the software makes a prediction in less than a minute.

Remember, in research contexts, it’s common not to know all the requirements upfront. Requirements evolve based on user feedback and project development.

Decomposing the Problem#

Breaking down a large problem into smaller, manageable tasks is critical for effective problem-solving.

  • Process: Start by identifying the major components necessary for the solution, such as data processing, model training, and results analysis. This method reduces complexity and makes the problem more approachable.

  • Independence: Aim for each component to be as independent as possible to minimize dependencies and simplify integration.

Planning the Codebase Structure#

Once the problem is decomposed, plan how the software or system will be structured.

  • Component Interaction: Define the inputs and outputs for each component and understand how these components will interact.

  • Tools: Utilize diagrams and models, such as Unified Modeling Language (UML), to visualize and plan the system architecture.

  • Programming Paradigms: Consider using Object-Oriented Programming (OOP) to encapsulate data and functions into objects, which can help in organizing code more efficiently.

Choosing the Right Data Representation#

Selecting an appropriate data structure is crucial as it can significantly impact the performance and complexity of the software.

  • Data Structures: Assess the operations that each component performs and choose data structures that enhance efficiency and performance. For example, a DataFrame may be used for its ease of manipulation and access.

Selecting Tools and Technologies#

The choice of tools and technologies can influence the development speed, application performance, and future maintenance.

  • Suitability and Familiarity: Balance between the best-suited tools for the project and those you are familiar with. Consider the learning curve and the project timeline.

  • Reusability and Licensing: Evaluate tools based on their reusability and licensing requirements. For instance, tools requiring fewer specific licenses are more accessible to a broader audience.

Designing for Change and Collaboration#

Design software with future modifications and teamwork in mind to facilitate maintenance and enhancements.

  • Modularity: Ensure each component has a single responsibility to simplify updates and maintenance.

  • Code Quality: Strive for code that is clean, understandable, and maintainable. Regularly refactoring and reviewing code practices helps in achieving better software quality.

Collaborative Development#

Engaging with peers during the development process can provide new insights and improve problem-solving.

  • Knowledge Sharing: Discussing issues and solutions with colleagues can help in refining ideas and avoiding potential pitfalls.

  • Coding Standards: Establish clear coding standards and conventions to maintain consistency across the team.

Adapted Content From:

Summary Quiz#