Skip to content

Commit

Permalink
🎨 Make Workbench formatting changes for section 3
Browse files Browse the repository at this point in the history
  • Loading branch information
bielsnohr committed Nov 26, 2024
1 parent 7c22e79 commit 1a88b94
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 98 deletions.
41 changes: 16 additions & 25 deletions episodes/30-section3-intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,25 @@ and look at the bigger picture of software as a *process* of development.

> *"If you fail to plan, you are planning to fail."* - Benjamin Franklin
{% comment %}
![](fig/section3-overview.png){alt='Software design and architecture' .image-with-shadow width="800px" }
{% endcomment %}
![](fig/section3-overview.svg){alt='Software design and architecture overview flowchart'}

![](fig/section3-overview.svg){alt='Software design and architecture' .image-with-shadow width="1000px" }
{% comment %}
flowchart LR
A(1. Setting up
software environment)
\--> B(2. Verifying
software correctness)
\--> C(3. Software development
as a process

```
- Software requirements
- Software architecture & design
- Programming paradigms
)
```

\--> D(4. Collaborative
development for reuse)
\--> E(5. Managing software
over its lifetime)
<!---
Source of the above image can be rendered in the Mermaid live editor:
<https://mermaid.live/edit#pako:eNplkU1rwzAMhv-K8WGk0Ab2dclhsLW9rTBW2GH4oiVKakikTJZTSul_n9M122A-2dKj95Wsoy25QlvYuuV9uQNR8_zq6DG7zs0WVT01JvaOAte6B0GDNHhh6pB05mixeDBP2U1u3lB8fUj0H7RkESyVMIQLusxuk-yUr3DAlvtRyhEEA6YXLhPtyJFJZ_HLCn5GLziy4V8SpNx5TVYxPa6SbvDNj8SLcCPQdeMkPQhUvukuEpeuVtldbpbctvDBAuoHdPSnN1OzJP8Y8MKvs_vcbICgGTWncR3xgGK8BtP6GtV3OLNz26F04Kv0w8fR1FndpSmcLdK1whpiq846OiUUovL2QKUtVCLObewrUFx5GPu3RQ1tSFGsvLJsvrd2Xt5Ers-ZqboHemee6k5flmapmQ>
{% endcomment %}
The mermaid source (with one less dash in arrows than needed):
flowchart LR
A(1. Setting up software environment)
A -> B(2. Verifying software correctness)
B -> C(3. Software development as a process
- Software requirements
- Software architecture & design
- Programming paradigms)
C -> D(4. Collaborative development for reuse)
D -> E(5. Managing software over its lifetime)
-->

## Writing Code vs Engineering Software

Expand Down
147 changes: 74 additions & 73 deletions episodes/34-code-refactoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -281,49 +281,52 @@ i.e. their tests are:
- **easier to maintain** - if at some point the data format changes
from CSV to JSON, the bulk of the tests need not be updated

> ## Exercise: Testing a Pure Function
>
> Add tests for `compute_standard_deviation_by_data()` that check for situations
> when there is only one file with multiple rows,
> multiple files with one row, and any other cases you can think of that should be tested.
>
> > ## Solution
> >
> > You might have thought of more tests, but we can easily extend the test by parametrizing
> > with more inputs and expected outputs:
> >
> > ```python
> > @pytest.mark.parametrize('data,expected_output', [
> > ([[[0, 1, 0], [0, 2, 0]]], [0, 0, 0]),
> > ([[[0, 2, 0]], [[0, 1, 0]]], [0, math.sqrt(0.25), 0]),
> > ([[[0, 1, 0], [0, 2, 0]], [[0, 1, 0], [0, 2, 0]]], [0, 0, 0])
> > ],
> > ids=['Two patients in same file', 'Two patients in different files', 'Two identical patients in two different files'])
> > def test_compute_standard_deviation_by_day(data, expected_output):
> > from inflammation.compute_data import compute_standard_deviation_by_data
> >
> > result = compute_standard_deviation_by_data(data)
> > npt.assert_array_almost_equal(result, expected_output)
> > ```
::: challenge
## Exercise: Testing a Pure Function

Add tests for `compute_standard_deviation_by_data()` that check for situations
when there is only one file with multiple rows,
multiple files with one row, and any other cases you can think of that should be tested.

:::: solution

You might have thought of more tests, but we can easily extend the test by parametrizing
with more inputs and expected outputs:

```python
@pytest.mark.parametrize('data,expected_output', [
([[[0, 1, 0], [0, 2, 0]]], [0, 0, 0]),
([[[0, 2, 0]], [[0, 1, 0]]], [0, math.sqrt(0.25), 0]),
([[[0, 1, 0], [0, 2, 0]], [[0, 1, 0], [0, 2, 0]]], [0, 0, 0])
],
ids=['Two patients in same file', 'Two patients in different files', 'Two identical patients in two different files'])
def test_compute_standard_deviation_by_day(data, expected_output):
from inflammation.compute_data import compute_standard_deviation_by_data

result = compute_standard_deviation_by_data(data)
npt.assert_array_almost_equal(result, expected_output)
```
> {: .solution}
{: .challenge}

> ## Functional Programming
> **Functional programming** is a programming paradigm where programs are constructed by
> applying and composing/chaining pure functions.
> Some programming languages, such as Haskell or Lisp, support writing pure functional code only.
> Other languages, such as Python, Java, C++, allow mixing **functional** and **procedural**
> programming paradigms.
> Read more in the [extra episode on functional programming](../functional-programming/index.html)
> and when it can be very useful to switch to this paradigm
> (e.g. to employ MapReduce approach for data processing).
{: .callout}


There are no definite rules in software design but making your complex logic out of
composed pure functions is a great place to start when trying to make your code readable,

::::
:::

::: callout

## Functional Programming

**Functional programming** is a programming paradigm where programs are constructed by
applying and composing/chaining pure functions.
Some programming languages, such as Haskell or Lisp, support writing pure functional code only.
Other languages, such as Python, Java, C++, allow mixing **functional** and **procedural**
programming paradigms.
Read more in the [extra episode on functional programming](../learners/functional-programming.md)
and when it can be very useful to switch to this paradigm
(e.g. to employ MapReduce approach for data processing).

:::

There are no definite rules in software design but making your complex logic out of
composed pure functions is a great place to start when trying to make your code readable,
testable and maintainable. This is particularly useful for:

* Data processing and analysis
Expand All @@ -339,46 +342,46 @@ which are characteristics of (but not limited to) the object-oriented programmin
In this episode, we mentioned [pure functions](./index.html#pure-functions)
and Functional Programming.

These are examples of different [programming paradigms](/programming-paradigms/index.html)
These are examples of different [programming paradigms](../learners/programming-paradigms.md)
and provide varied approaches to structuring your code -
each with certain strengths and weaknesses when used to solve particular types of problems.
In many cases, particularly with modern languages, a single language can allow many different
structural approaches and mixing programming paradigms within your code.
Once your software begins to get more complex - it is common to use aspects of [different paradigm](../programming-paradigms/index.html)
Once your software begins to get more complex - it is common to use aspects of [different paradigm](../learners/programming-paradigms.md)
to handle different subtasks.
Because of this, it is useful to know about the [major paradigms](../programming-paradigms/index.html),
Because of this, it is useful to know about the [major paradigms](../learners/programming-paradigms.md),
so you can recognise where it might be useful to switch.
This is outside of scope of this course - we have some extra episodes on the topics of
[procedural programming](../procedural-programming/index.html),
[functional programming](../functional-programming/index.html) and
[object-oriented programming](../object-oriented-programming/index.html) if you want to know more.

> ## So Which One is Python?
> Python is a multi-paradigm and multi-purpose programming language.
> You can use it as a procedural language and you can use it in a more object oriented way.
> It does tend to land more on the object oriented side as all its core data types
> (strings, integers, floats, booleans, lists,
> sets, arrays, tuples, dictionaries, files)
> as well as functions, modules and classes are objects.
>
> Since functions in Python are also objects that can be passed around like any other object,
> Python is also well suited to functional programming.
> One of the most popular Python libraries for data manipulation,
> [Pandas](https://pandas.pydata.org/) (built on top of NumPy),
> supports a functional programming style
> as most of its functions on data are not changing the data (no side effects)
> but producing a new data to reflect the result of the function.
{: .callout}
[procedural programming](../learners/procedural-programming.md),
[functional programming](../learners/functional-programming.md) and
[object-oriented programming](../learners/object-oriented-programming.md) if you want to know more.

::: callout

## So Which One is Python?

Python is a multi-paradigm and multi-purpose programming language.
You can use it as a procedural language and you can use it in a more object oriented way.
It does tend to land more on the object oriented side as all its core data types
(strings, integers, floats, booleans, lists,
sets, arrays, tuples, dictionaries, files)
as well as functions, modules and classes are objects.

Since functions in Python are also objects that can be passed around like any other object,
Python is also well suited to functional programming.
One of the most popular Python libraries for data manipulation,
[Pandas](https://pandas.pydata.org/) (built on top of NumPy),
supports a functional programming style
as most of its functions on data are not changing the data (no side effects)
but producing a new data to reflect the result of the function.
:::

## Software Design and Architecture

In this section so far we have been talking about **software design** - the individual modules and
components of the software. We are now going to have a brief look into **software architecture** -
which is about the overall structure that these software components fit into, a *design pattern*
with a common successful use of software components.

{% include links.md %}
```
In this section so far we have been talking about **software design** - the individual modules and
components of the software. We are now going to have a brief look into **software architecture** -
which is about the overall structure that these software components fit into, a *design pattern*
with a common successful use of software components.

:::::::::::::::::::::::::::::::::::::::: keypoints

Expand All @@ -387,5 +390,3 @@ with a common successful use of software components.
- Using pure functions that process data without side effects whenever possible makes the code easier to understand, test and maintain.

::::::::::::::::::::::::::::::::::::::::::::::::::

0 comments on commit 1a88b94

Please sign in to comment.