We closed the previous lesson with easytask.py working and an obvious limitation: all it does is print fixed text, and changing a piece of data means editing the code by hand. The temptation now is to rush off and learn syntax to fix it. We are going to resist that for one more lesson, because the skill that really separates whoever programs from whoever copies code is still missing: thinking the solution through before writing it.
A programmer in a hurry opens the editor and starts typing. Two hours later they have code that almost works, they do not know why it fails and they cannot explain to anyone what it does. A skilled programmer spends the first twenty minutes on paper: they understand the problem, break it down, write out the steps and check them by hand. Then they type, and they type little, because they already know what they are going to write.
In this lesson you will learn what an algorithm is exactly, how to break a problem down, how to express a solution in pseudocode and in a flowchart, and how to verify it without a computer by means of a desk check. All applied to two real EasyTask operations.
Constructions such as "repeat" or "if...then" will appear: here we will use them purely as a way of thinking. Writing them in Python is a matter for modules 2 and 3.
Contents
- What an algorithm is
- The five properties of an algorithm
- Breaking a problem into steps and subproblems
- Pseudocode: conventions and example
- Flowcharts
- Desk check: verifying without a computer
- From pseudocode to Python code
- EasyTask: registering a new task
- EasyTask: which task Marta tackles first
- Common mistakes and tips
- Exercises
- Conclusion
- What an algorithm is
An algorithm is a finite sequence of precise steps which, starting from some input data, produces a result in a finite time.
The word sounds technical, but the concept is an everyday one: a cooking recipe, the assembly instructions for a bookshelf and the multiplication procedure you learned at school are all algorithms. They share the essentials: ordered, unambiguous steps that terminate and produce something.
The important part is this: an algorithm is independent of the programming language. The same algorithm for sorting a list can be written in Python, in Java or on paper; what changes is the notation, not the idea. That is why what you learn here will serve you even if you change language ten times.
| Concept | What it is | Analogy |
|---|---|---|
| Problem | What has to be solved | "I want a cake" |
| Algorithm | The method for solving it | The recipe |
| Program | The algorithm written in an executable language | The recipe translated into orders for a kitchen robot |
| Execution | The program running with specific data | Making the cake on Saturday |
Confusing these four things is the source of a lot of frustration. "My program isn't working" usually really means "I am not clear about the algorithm", and that is not fixed by fiddling with code.
- The five properties of an algorithm
Not every list of steps is an algorithm. It must satisfy five properties.
1. Precise. Each step states exactly what to do, with no room for interpretation.
- Bad: "review the important tasks".
- Good: "for each task, if its priority is high and its status is pending, show it on screen".
2. Definite (deterministic). With the same inputs it always produces the same outputs. If you run the algorithm twice with the same data, the result is identical.
3. Finite. It terminates after a finite number of steps. An algorithm that does not terminate is not an algorithm, it is an infinite loop, and it is one of the most common errors when starting out.
- Bad: "repeat: count one more task" (it never ends).
- Good: "repeat while there are tasks left to review" (it ends, because tasks are finite and each round leaves one fewer).
4. With defined input. Zero or more starting data items, clearly specified. In "register a task", the input is the title, the description, the assignee and the priority.
5. With defined output. At least one observable result: a value, a message on screen, a modified file. An algorithm that produces nothing observable is of no use at all.
| Property | Control question | If it fails... |
|---|---|---|
| Precise | Can anyone read this step in two ways? | The program will do something unexpected |
| Definite | Will it always give the same result with the same data? | Errors impossible to reproduce |
| Finite | Is it guaranteed to terminate? | The program hangs |
| Defined input | What data do I need and where does it come from? | Data will be missing halfway through |
| Defined output | What does it produce and how do I see it? | Nobody will know whether it worked |
Apply these five questions to any algorithm you write. They catch most faults before they exist.
- Breaking a problem into steps and subproblems
The central technique for tackling any problem is called decomposition: splitting a large problem into smaller problems until each piece is obvious. Each piece is solved separately and then they are combined.
Applied to EasyTask, Marta's initial request was: "I want a program to manage the studio's tasks". Like that, as one block, it is unmanageable. Decomposed:
flowchart TD
A["Manage Alba Studio tasks"] --> B["Register a task"]
A --> C["Query tasks"]
A --> D["Update tasks"]
A --> E["Save the information"]
B --> B1["Ask for the data"]
B --> B2["Validate priority and assignee"]
B --> B3["Add to the list"]
C --> C1["List them all"]
C --> C2["Filter by assignee"]
C --> C3["Filter by status"]
D --> D1["Mark as completed"]
D --> D2["Change assignee"]
Each leaf of the tree is a small task we do know how to tackle. "Mark as completed" is a manageable problem; "manage the studio's tasks" was not.
Decomposition brings three concrete advantages:
- Visible progress. Solving one leaf of the tree takes minutes, and you see movement. Facing the whole problem produces paralysis.
- Localised errors. If filtering by assignee fails, you know exactly which piece to look at.
- Reuse. "Validate priority" serves both when registering a task and when modifying one. Writing it once and using it twice is the basis of module 4.
A practical criterion for knowing when to stop decomposing: when you can explain the piece in one sentence and you know how to do it by hand. If you are still unsure, keep splitting.
- Pseudocode: conventions and example
Pseudocode is a way of writing algorithms halfway between English and code: structured enough not to be ambiguous, free enough not to fight with syntax.
There is no official pseudocode. These are the conventions we will use in the course:
| Element | Notation | Example |
|---|---|---|
| Start and end | START / END |
|
| Data input | READ <item> |
READ title |
| Data output | DISPLAY <message> |
DISPLAY "Task saved" |
| Assign a value | <name> ← <value> |
counter ← 0 |
| Condition | IF <cond> THEN ... ELSE ... END IF |
|
| Conditional repetition | WHILE <cond> DO ... END WHILE |
|
| Repetition over elements | FOR EACH <x> IN <list> DO ... END FOR |
|
| Comment | // text |
// ignored when running |
Two important style rules: indent the contents of each block (it makes it easy to see where it starts and ends) and always close the blocks (END IF, END WHILE).
A complete example. An algorithm that works out how many pending tasks the studio has:
START
// Input: a list of tasks, each with its status
// Output: the number of pending tasks
pending ← 0
FOR EACH task IN task_list DO
IF status of task = "pending" THEN
pending ← pending + 1
END IF
END FOR
DISPLAY "Pending tasks: " + pending
ENDLet us run the five properties over this algorithm:
- Precise: each step is unambiguous.
- Definite: the same list always produces the same number.
- Finite: the list has a finite number of elements and each round consumes one.
- Defined input: the list of tasks with their statuses.
- Defined output: a message with the number of pending tasks.
It satisfies all five. It is a correct algorithm, and we have verified it without switching the computer on.
- Flowcharts
A flowchart represents the algorithm graphically. It is especially useful when there are decisions and alternative paths, because they can be seen at a glance.
The basic symbols:
| Symbol | Shape | Meaning |
|---|---|---|
| Start / End | Oval | Where it starts and ends |
| Process | Rectangle | An action or calculation |
| Decision | Diamond | A question with Yes/No exits |
| Input / Output | Parallelogram | Reading data or showing results |
| Arrow | — | The order in which you move on |
Example 1: is the task urgent? An algorithm with a single decision.
flowchart TD
A(["START"]) --> B[/"READ priority of the task"/]
B --> C{"priority = high?"}
C -->|Yes| D[/"DISPLAY: Deal with it today"/]
C -->|No| E[/"DISPLAY: It can wait"/]
D --> F(["END"])
E --> F
Note two things: exactly two labelled arrows leave the diamond, and both paths join up again before the end. A diagram with paths that do not finish at END is incomplete.
Example 2: counting the pending tasks. The same algorithm as in the previous section, now with repetition.
flowchart TD
A(["START"]) --> B["pending <- 0"]
B --> C["Move to the first task"]
C --> D{"Any tasks left<br/>to review?"}
D -->|No| H[/"DISPLAY pending"/]
D -->|Yes| E{"Is its status<br/>pending?"}
E -->|Yes| F["pending <- pending + 1"]
E -->|No| G["Move to the next task"]
F --> G
G --> D
H --> I(["END"])
The loop shows up as what it is: an arrow that goes back, from G to D. And there lies the key to finiteness: G moves on to the next task on every round, so at some point the answer to D will be "No". If G did not exist, the diagram would spin forever. That return arrow is the infinite loop made visible, and it is a good reason to draw before you program.
| Tool | When it is worth using |
|---|---|
| Pseudocode | Long algorithms, many sequential steps, already close to the code |
| Flowchart | Few steps but many decisions; explaining the logic to someone else |
In practice both are used: the diagram to grasp the overall shape, the pseudocode for the detail.
- Desk check: verifying without a computer
A desk check (or trace) consists of running the algorithm by hand, with specific data, noting in a table how each value changes step by step. It is the most underrated and most profitable technique in the whole trade: it catches logic errors in five minutes that would cost an hour at the computer.
Let us trace the pending-count algorithm with this Alba Studio data:
| No. | Task | Assignee | Status |
|---|---|---|---|
| 1 | Solé Bakery logo | Luis | pending |
| 2 | Book fair poster | Nuria | completed |
| 3 | Vidal account website redesign | Luis | pending |
| 4 | March quote | Marta | pending |
And now the trace table. One row per loop round, one column per value we care about:
| Round | Task examined | Status | Is it pending? | pending afterwards |
|---|---|---|---|---|
| — | (start) | — | — | 0 |
| 1 | Solé Bakery logo | pending | Yes | 1 |
| 2 | Book fair poster | completed | No | 1 |
| 3 | Vidal account website redesign | pending | Yes | 2 |
| 4 | March quote | pending | Yes | 3 |
| — | (end: no tasks left) | — | — | 3 |
Output: Pending tasks: 3. Counting by eye in the data table: numbers 1, 3 and 4. Correct.
How to do a desk check properly:
- Choose small but representative data. Four elements are enough; with forty you will get tired and skip steps.
- One column for each value that changes. If there are three variables, three columns.
- One row per step or round. No grouping and no "speeding up": the error is usually precisely where something is taken for granted.
- Be the machine, not the author. Do not do what you meant to write, do what is written. This is where the errors show up.
- Test the edge cases too. What if the list is empty? With our algorithm the loop never runs and the output is
0. Correct. What if they are all completed? Also0. Correct.
That last point deserves emphasis: edge cases are where most real errors live. Empty list, a single element, all the same, repeated values. Always check them.
- From pseudocode to Python code
Once the algorithm is clear and traced, translating it into Python is almost mechanical. Let us see it with an example we can already write in full: showing a task card.
Pseudocode:
START
DISPLAY "--- TASK CARD ---"
DISPLAY "Title: Sole Bakery logo"
DISPLAY "Assignee: Luis"
DISPLAY "Priority: high"
DISPLAY "Status: pending"
ENDPython:
print("--- TASK CARD ---")
print("Title: Sole Bakery logo")
print("Assignee: Luis")
print("Priority: high")
print("Status: pending")The correspondence is direct: DISPLAY becomes print, and the text goes between quotes inside the parentheses. START and END are not translated: in Python the program begins at the first line and ends at the last.
This is the complete translation table, which we will fill in as the course goes on:
| Pseudocode | Python | Where it is studied |
|---|---|---|
DISPLAY x |
print(x) |
You already know it |
READ x |
x = input() |
Input and output |
x ← 5 |
x = 5 |
Variables |
IF ... THEN |
if ...: |
Conditionals |
ELSE |
else: |
Conditionals |
WHILE ... DO |
while ...: |
Loops |
FOR EACH x IN list |
for x in list: |
Loops |
For now you only have the first row. By the end of module 3 you will have them all, and you will be able to translate into Python any algorithm you write in pseudocode. In the meantime, write pseudocode without fear: the algorithm is the valuable part, and translating it will be the easy bit.
- EasyTask: registering a new task
Let us apply all of the above to EasyTask's first requirement (R1 and R2 from the list in the first lesson): registering a task with its five data items, validating the priority.
The problem. Marta wants to note down a new job. We have to ask her for the title, description, assignee and priority; the status always starts as "pending". The priority can only be high, medium or low: if she types anything else, we have to ask again.
Pseudocode:
START
// Input: data typed by the user
// Output: the registered task and a confirmation message
DISPLAY "--- NEW TASK ---"
READ title
READ description
READ assignee
// Validation: repeat until the priority is valid
priority_valid ← FALSE
WHILE priority_valid = FALSE DO
DISPLAY "Priority (high / medium / low):"
READ priority
IF priority = "high" OR priority = "medium" OR priority = "low" THEN
priority_valid ← TRUE
ELSE
DISPLAY "Invalid priority. Please try again."
END IF
END WHILE
status ← "pending"
SAVE the task (title, description, assignee, priority, status)
DISPLAY "Task registered successfully."
ENDFlowchart:
flowchart TD
A(["START"]) --> B[/"READ title, description,<br/>assignee"/]
B --> C[/"READ priority"/]
C --> D{"is priority<br/>high, medium or low?"}
D -->|No| E[/"DISPLAY: invalid priority"/]
E --> C
D -->|Yes| F["status <- pending"]
F --> G["SAVE the task"]
G --> H[/"DISPLAY: task registered"/]
H --> I(["END"])
Note the arrow that goes back from E to C: that is the validation loop. As long as the priority is wrong, the question is asked again. And it is finite provided the user eventually types something valid; if they type nonsense indefinitely, the program will ask indefinitely. That is not an error in the algorithm: it is a design decision worth taking consciously. An alternative would be to allow three attempts and then cancel.
Desk check. Marta registers a job and gets the priority wrong:
| Step | Action | Value entered | State of the algorithm |
|---|---|---|---|
| 1 | READ title | "Vidal business cards" | title assigned |
| 2 | READ description | "300 units, double-sided" | description assigned |
| 3 | READ assignee | "Nuria" | assignee assigned |
| 4 | READ priority | "urgent" | not valid → error message |
| 5 | READ priority | "HIGH" | is it valid? |
| 6 | READ priority | "high" | valid → leaves the loop |
| 7 | status ← pending | — | status = "pending" |
| 8 | SAVE and DISPLAY | — | "Task registered successfully." |
Step 5 reveals a problem that the desk check has brought to the surface: "HIGH" in capitals does not match "high", because they are different pieces of text. The algorithm, as written, would reject it. Is that what we want? Almost certainly not: Marta will type in capitals half the time.
The fix is simple — convert what is entered to lower case before comparing — and we will apply it in Type conversion and validation. What matters here is how we found the fault: with a table and a pencil, before writing a single line of Python. Finding it later, with the program already written, would have cost far more.
- EasyTask: which task Marta tackles first
A second algorithm, this time about deciding. Marta arrives on Monday, has several tasks assigned and wants to know which one to start with.
The business rule, agreed with the team:
- Only pending tasks count: completed ones are ignored.
- Among the pending ones, the one with the highest priority wins (
high>medium>low). - If there is a tie on priority, the one registered earlier wins.
Note that these three rules are not invented by the programmer: they are agreed with whoever has the problem. Writing them down explicitly is part of the job, and often the first time the team has agreed on something they thought was obvious.
Pseudocode:
START
// Input: Marta's list of tasks, in registration order
// Output: the task she should tackle first
chosen ← NONE
FOR EACH task IN martas_tasks DO
IF status of task = "completed" THEN
// of no interest to us, move on to the next one
ELSE
IF chosen = NONE THEN
chosen ← task
ELSE
IF priority of task is higher than priority of chosen THEN
chosen ← task
END IF
// if it is equal or lower, the previous one stays:
// this way the one registered earlier wins on a tie
END IF
END IF
END FOR
IF chosen = NONE THEN
DISPLAY "You have no pending tasks."
ELSE
DISPLAY "Start with: " + title of chosen
END IF
ENDFlowchart:
flowchart TD
A(["START"]) --> B["chosen <- NONE"]
B --> C{"Any tasks left<br/>to review?"}
C -->|No| J{"chosen = NONE?"}
C -->|Yes| D{"Is it completed?"}
D -->|Yes| I["Move to the next one"]
D -->|No| E{"chosen = NONE?"}
E -->|Yes| F["chosen <- current task"]
E -->|No| G{"Is its priority higher<br/>than that of chosen?"}
G -->|Yes| F
G -->|No| I
F --> I
I --> C
J -->|Yes| K[/"DISPLAY: no pending tasks"/]
J -->|No| L[/"DISPLAY: start with chosen"/]
K --> M(["END"])
L --> M
Desk check. Marta's tasks, in registration order:
| No. | Title | Priority | Status |
|---|---|---|---|
| 1 | Vidal account quote | medium | pending |
| 2 | Review February invoices | low | completed |
| 3 | Call Solé Bakery | high | pending |
| 4 | Prepare team meeting | high | pending |
Trace round by round:
| Round | Task | Completed? | chosen before |
Replaces? | chosen after |
|---|---|---|---|---|---|
| 1 | Vidal quote (medium) | No | NONE | Yes, there was none | Vidal quote |
| 2 | Review invoices (low) | Yes | Vidal quote | No, it is ignored | Vidal quote |
| 3 | Call Solé (high) | No | Vidal quote | Yes: high > medium | Call Solé |
| 4 | Prepare meeting (high) | No | Call Solé | No: high is not higher than high | Call Solé |
Output: Start with: Call Solé Bakery.
Let us verify that this is correct according to the agreed rules. There are three pending tasks: Quote (medium), Call Solé (high) and Prepare meeting (high). Two are high priority, and between them the one registered earlier wins, which is "Call Solé" (number 3 against number 4). It matches what the algorithm produces.
And the edge cases:
- Marta has no tasks at all. The loop never runs,
chosenstays NONE and "You have no pending tasks" is shown. Correct. - They are all completed. They all fall down the branch that ignores them,
chosenstays NONE and the same message comes out. Correct. - Only one pending. It is assigned on its round and nothing replaces it. Correct.
The algorithm holds up in all four scenarios. It is ready to be implemented, and we will do so once we have conditionals and loops in Python.
Common Mistakes and Tips
Starting to type without having thought the algorithm through. It is the costliest mistake. If you cannot say out loud what steps your program is going to take, you are not ready to write it. Paper first.
Ambiguous steps. "Check whether the task is important" is not a step: it does not say what important means. "Check whether its priority is high" is. Every ambiguity you leave in the algorithm will reappear as an error in the program.
Forgetting to advance inside a loop. If nothing changes on each round to bring the end closer, the loop is infinite. It is easy to spot in the diagram: look for the box that makes the diamond's condition progress. If you cannot find it, you have a problem.
Skipping the edge cases. Empty list, a single element, all with the same value, all completed. An algorithm that only works with the pretty case does not work.
Doing the desk check "as the author" and not "as the machine". When tracing you tend to run what you meant to write, not what you wrote. It is the subtlest trap. A trick: trace an algorithm of your own from a week ago, or swap with someone else.
Taking business rules for granted. "The highest priority wins" seems complete until two tasks tie. Always write down what happens on ties, on empty data and on incorrect data. Asking beforehand is cheap; discovering it in production is not.
Believing that pseudocode has to be perfect. It is not a deliverable, it is a thinking tool. Cross it out, rewrite it, use arrows in the margin. If it helps you think, it is well written.
A final tip: when a program comes out wrong, do not start changing code to see if you hit on the answer. Go back to the algorithm and give it a desk check. In most cases the error is not in the syntax, it is in the reasoning.
Exercises
Exercise 1: Spotting unmet properties
For each algorithm, state which property or properties it fails to meet and correct it:
a)
b)
c)
Exercise 2: Algorithm and diagram for counting one person's tasks
Write the pseudocode and the flowchart of an algorithm that, given the studio's list of tasks and a person's name, shows how many pending tasks they have assigned. Then do the desk check with this data, looking for Luis's:
| No. | Title | Assignee | Status |
|---|---|---|---|
| 1 | Solé Bakery logo | Luis | pending |
| 2 | Book fair poster | Nuria | pending |
| 3 | Vidal website redesign | Luis | completed |
| 4 | Solé brand manual | Luis | pending |
| 5 | March quote | Marta | pending |
Exercise 3: Reassigning a task
Marta wants to be able to reassign a task to another member of the team. The agreed rules are:
- Only pending tasks can be reassigned; a completed one is not touched.
- The new assignee must be Marta, Luis or Nuria.
- There is no sense in reassigning to the same person who already has it: a warning is needed.
Write the pseudocode of this algorithm and do a desk check for these three cases: (a) reassigning to Nuria a pending task of Luis's, (b) trying to reassign a completed task, (c) reassigning to Luis a task that is already Luis's.
Solutions
Solution 1.
a) It fails finiteness. Nothing inside the loop reduces the number of tasks or advances through the list, so the condition never stops holding: the message would be printed forever. It also has no useful output (it repeats the same thing without reporting anything). Correction:
START
pending ← 0
FOR EACH task IN list DO
IF status of task = "pending" THEN
pending ← pending + 1
END IF
END FOR
DISPLAY "Pending tasks: " + pending
ENDb) It fails precision (and therefore determinism). "Seems urgent" cannot be evaluated: two people would read it differently and the machine cannot read it at all. Correction:
START
READ priority
IF priority = "high" THEN
DISPLAY "Deal with it soon"
ELSE
DISPLAY "It can wait"
END IF
ENDThe ELSE has been added so that there is output in both cases.
c) It fails defined output. It works the counter out correctly but never shows it: the result is lost when it finishes. Correction: add DISPLAY "Total tasks: " + counter before END.
Solution 2.
Pseudocode:
START
// Input: list of tasks and a person's name
// Output: number of pending tasks for that person
READ person
counter ← 0
FOR EACH task IN task_list DO
IF assignee of task = person AND status of task = "pending" THEN
counter ← counter + 1
END IF
END FOR
DISPLAY person + " has " + counter + " pending tasks."
ENDFlowchart:
flowchart TD
A(["START"]) --> B[/"READ person"/]
B --> C["counter <- 0"]
C --> D{"Any tasks left<br/>to review?"}
D -->|No| H[/"DISPLAY person and counter"/]
D -->|Yes| E{"Is it that person's<br/>AND is it pending?"}
E -->|Yes| F["counter <- counter + 1"]
E -->|No| G["Move to the next one"]
F --> G
G --> D
H --> I(["END"])
Desk check looking for Luis's:
| Round | Task | Is it Luis's? | Pending? | Does it count? | counter |
|---|---|---|---|---|---|
| — | (start) | — | — | — | 0 |
| 1 | Solé Bakery logo | Yes | Yes | Yes | 1 |
| 2 | Book fair poster | No | Yes | No | 1 |
| 3 | Vidal website redesign | Yes | No | No | 1 |
| 4 | Solé brand manual | Yes | Yes | Yes | 2 |
| 5 | March quote | No | Yes | No | 2 |
Output: Luis has 2 pending tasks. Verified by eye: numbers 1 and 4. Number 3 is Luis's but it is completed, and that is precisely the case that checks the double condition works.
Solution 3.
START
// Input: a task and the name of the new assignee
// Output: the reassigned task, or a message explaining why not
READ task
READ new_assignee
IF status of task = "completed" THEN
DISPLAY "Cannot reassign: the task is already completed."
ELSE
IF new_assignee IS NOT "Marta" NOR "Luis" NOR "Nuria" THEN
DISPLAY "Invalid assignee. It must be Marta, Luis or Nuria."
ELSE
IF new_assignee = assignee of task THEN
DISPLAY "The task is already assigned to " + new_assignee
ELSE
assignee of task ← new_assignee
DISPLAY "Task reassigned to " + new_assignee
END IF
END IF
END IF
ENDDesk check:
| Case | Task (assignee, status) | New assignee | Checks | Result |
|---|---|---|---|---|
| a | Solé logo (Luis, pending) | Nuria | Not completed → valid assignee → different from the current one | assignee ← Nuria. "Task reassigned to Nuria" |
| b | Vidal website redesign (Luis, completed) | Nuria | Completed → it stops at the first condition | "Cannot reassign: the task is already completed." |
| c | Brand manual (Luis, pending) | Luis | Not completed → valid assignee → same as the current one | No changes. "The task is already assigned to Luis" |
Notice the order of the checks: first the status, then the validity of the name and lastly the match. That order matters. If we checked the assignee match first, a completed task assigned to Luis that someone tried to reassign to Luis would give the wrong message. Deciding the order in which the checks are made is part of designing the algorithm, not a detail.
Conclusion
Programming starts a long way from the keyboard. In this lesson you have learned that an algorithm is a finite sequence of precise steps that turn an input into an output, independent of the language it is written in, and that it must satisfy five properties: being precise, definite, finite, with defined input and with defined output. You have seen how to decompose a large problem into manageable subproblems, how to express the solution in pseudocode with clear conventions and how to draw it in a flowchart where loops show up as arrows that go back. And you have practised the most profitable technique in the trade: the desk check, which with a table and a pencil finds errors that would cost hours at the computer — such as the "HIGH" that did not match "high".
All of it applied to EasyTask: we now have the algorithms for registering a new task and for deciding which task Marta tackles first designed, verified and with their edge cases checked. They are not sketches: they are specifications ready to implement.
With this we close module 1. You know what programming is, where the trade comes from, how languages are classified and chosen, you have a working environment with easytask.py on your disk and you know how to design an algorithm before writing it. It is exactly the kit needed to start writing real code.
And that is where we are heading now. In module 2 we leave the paper behind and return to Python with the piece that solves the limitation we have been carrying since the previous lesson — a program that only prints fixed text: variables, which let us store data and work with it. We will start with Variables and data types, where at last a task's title, assignee and priority will stop being written by hand inside a print and will become information the program handles.
Fundamentals of Programming
Module 1: Introduction to Programming
- What is programming?
- History of programming
- Programming languages
- Development environments
- From problem to algorithm
Module 2: Core Concepts
- Variables and data types
- Operators and expressions
- Input and output
- Type conversion and data validation
Module 3: Control Structures
Module 4: Functions and Procedures
- Defining and using functions
- Parameters and return values
- Variable scope
- Breaking a program down into functions
- Functions as values: lambda and higher order
Module 5: Data Structures
- Lists and arrays
- Strings
- Dictionaries and sets
- Tuples and nested structures
- Saving data to files: text, CSV and JSON
Module 6: Basic Algorithms
Module 7: Objects and Code Organisation
- From data to objects: classes and instances
- Attributes, methods and the constructor
- Collections of objects
- Modules, packages and imports
Module 8: Good Practices and Tools
- Documentation and comments
- Debugging and error handling
- Version control
- Automated testing
- Style, readability and refactoring
