-
-
Notifications
You must be signed in to change notification settings - Fork 139
SDC Types Rework #2018
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
LonMcGregor
wants to merge
35
commits into
main
Choose a base branch
from
lm-sdc-tools-5-rework
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
SDC Types Rework #2018
Changes from all commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
ecdeb60
Remove the unnecessary sidebar text
d1abcff
rework intro to types
8514728
merge poonam's dataclass change
a4cead8
update classes
6c24cf1
update methods
d8bb2b5
update dataclass task description
777753f
generics
ef57493
refactoring
701e199
enums
13d87dc
inheritance
58f189c
add encapsulation task
ea7472f
add encapsulation stretch task
615f33c
Spelling pass 1
85e6ee3
language pass 2
d4d6774
language pass 3
eabce4c
Make tasks consistent
9d1b2b4
Add the encapsulation prep
675a451
formatting
39cc20b
LOs
f83812f
update task text
7121e12
Merge branch 'main' into lm-sdc-tools-5-rework
LonMcGregor 46bd2a2
Merge branch 'main' into lm-sdc-tools-5-rework
illicitonion 19a988d
Update common-content/en/module/decomposition/classes-and-objects/ind…
LonMcGregor 4bb72da
review types intro
2109f4a
Merge remote-tracking branch 'refs/remotes/origin/lm-sdc-tools-5-rewo…
a92f4e6
review example code quality
c377f97
Update common-content/en/module/decomposition/methods/index.md
LonMcGregor 834020f
Update common-content/en/module/decomposition/enums/index.md
LonMcGregor 7492121
Update common-content/en/module/decomposition/inheritance/index.md
LonMcGregor 6f81dbc
Update common-content/en/module/decomposition/inheritance/index.md
LonMcGregor aaf08a9
Update common-content/en/module/decomposition/generics/index.md
LonMcGregor 33194eb
Update common-content/en/module/decomposition/inheritance/index.md
LonMcGregor fc71d54
Update common-content/en/module/decomposition/inheritance/index.md
LonMcGregor d2b3543
Update common-content/en/module/decomposition/enums/index.md
LonMcGregor 2a363b9
review encapsulation summary
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
120 changes: 120 additions & 0 deletions
120
common-content/en/module/decomposition/encapsulation/index.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| +++ | ||
| title = "Encapsulation" | ||
| time = 30 | ||
| objectives = [ | ||
| "Define encapsulation.", | ||
| "Explain how encapsulation can benefit class design.", | ||
| ] | ||
|
|
||
| [build] | ||
| list = "local" | ||
| publishResources = false | ||
| render = "never" | ||
| +++ | ||
|
|
||
|
|
||
| An advantage of classes over objects is encapsulation. | ||
|
|
||
| Imagine you have written your Person class that stores age information. | ||
|
|
||
| For privacy reasons, you don't want to reveal the exact age of the person, only whether they are or are not over 18 years old. | ||
|
|
||
| This means we need to store the "age" value in a class, but somehow keep it _private_ to that class. The only _public_ information we want is whether or not they are over 18. How can we achieve this? | ||
|
|
||
| Look at the following code: | ||
|
|
||
| ```python | ||
| class Person: | ||
| def __init__(self, name: str, age: int): | ||
| self.name = name | ||
| self.__age = age | ||
|
|
||
| def is_adult(self): | ||
| return self.__age >= 18 | ||
|
|
||
| imran = Person("Imran", 22) | ||
| print(imran.name) | ||
| # print(imran.age) # fails | ||
| # print(imran.__age) # fails | ||
| print(imran.is_adult()) # works and prints True | ||
|
|
||
| eliza = Person("Eliza", 12) | ||
| print(eliza.name) | ||
| # print(eliza.age) # fails | ||
| # print(imran.__age) # fails | ||
| print(eliza.is_adult()) # works and prints False | ||
| ``` | ||
|
|
||
| > [!NOTE] | ||
| > | ||
| > It is important to be clear about the wording here as there are some subtle differences between fields and properties as used in classes. | ||
| > A "field" is the underlying part of a class that stores some value. | ||
| > A "property" is the publicly accessible part that you can access from outside the class. | ||
| > | ||
|
|
||
| In python, any field that begins with two underscores is considered _private_, i.e. it can only be used within that specific class instance. | ||
|
|
||
|
|
||
| > [!NOTE] | ||
| > | ||
| > Using underscores, Python doesn't have a clear way of marking something as private. | ||
| > Other programming languages like Java mark this more explicitly with keywords like "private" and "public". | ||
| > It's worth becoming familiar with this private/public language even if you're not using it right now. | ||
| > | ||
|
|
||
| You can now program classes to change behaviour based on the information stored within them. | ||
| Compare this with objects, which can only ever store data, and behave the same every time. | ||
|
|
||
| Another benefit of encapsulation is letting you make "read only" properties. | ||
| Think about the example above. | ||
| Imagine you wanted to check if a `Person` class had a certain name using an equality test, but accidentally used a single `=` symbol: | ||
| ```python | ||
| imran.name = "Eliza" | ||
| ``` | ||
| Python allows you to update public fields whenever you want. | ||
| If `name` were private, and the only way to access it was through a `get_name()` method that returns a string, it would be impossible to accidentally change the value. | ||
| In this way, encapsulation can be used to prevent accidental errors in code. | ||
|
|
||
| {{<note type="Reading">}} | ||
| Read through [Python encapsulation](https://www.w3schools.com/python/python_encapsulation.asp). | ||
|
|
||
| Do some further research of your own to learn about encapsulation. | ||
| {{</note>}} | ||
|
|
||
| {{<note type="exercise">}} | ||
| **Task 9** | ||
|
|
||
| Having done some research on encapsulation, think about the benefits. | ||
|
|
||
| Think of some examples and in your own words write down some benefits and trade-offs of using encapsulation in classes in the file `09-encapsulation.py` | ||
|
|
||
| **Stretch Task** | ||
|
|
||
| Working in file `09-encapsulation.py`, make the `name` field private, and add a `get_name()` method to allow read-only access. | ||
| {{</note>}} | ||
|
|
||
| ### Why encapsulate? | ||
|
|
||
| In your career you will rarely be building code used only once. | ||
| It is likely the code you write will sit alongside code written by others as part of a large long-lived codebase. | ||
| Classes and encapsulation are really important techniques as you move towards thinking about how others will use your code, and how you plan to make your code maintainable and reusable for future use. | ||
|
|
||
| Classes with encapsulation clearly define the outward-facing interface of what you are building. | ||
| Think about the documentation you may have read for well-defined APIs like [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) or [argparse](https://docs.python.org/3/library/argparse.html). | ||
| You don't need to know how they work internally to make use of them, and the methods and their parameters are clearly stated. | ||
| If `argparse` is updated, e.g. to make it more efficient, your code won't break as the public interface won't change. | ||
| If `fetch` is changed, e.g. adding a new parameter, type checking will immediately highlight everywhere you need to update your code. | ||
|
|
||
| Encapsulation also makes it easy to swap different implementations. | ||
| Imagine you started a big project with a python `dict` but later on needed to change it to an [OrderedDict](https://docs.python.org/3/library/collections.html#collections.OrderedDict). | ||
| The interfaces are almost exactly the same, so you wouldn't need to change any of the method invocations, making the change much easier and safer. | ||
|
|
||
| Encapsulation also helps with testing. | ||
| Only the public interface, methods and properties, need to be tested. | ||
| You can write the test before you start using test-driven development, defining the public interface and behaviour. | ||
| Then you can focus on the implementation inside, and when the test passes you know your class works. | ||
| Testing a single class with a well defined interface is much easier than needing to test lots of interconnected separate free functions. | ||
|
|
||
| Until now you have been solving small coding challenges with the aim of solving the specific task. | ||
| From now on you will start to think more about how you can build a solution that will adapt well to future changes. | ||
| Well defined classes that encapsulate your implementations will be a big help. | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.