DEV Community

Cover image for Mastering Functions: How to Write Functions That Will Take Your Skills to the Next Level
Max Shapira
Max Shapira

Posted on • Updated on

Mastering Functions: How to Write Functions That Will Take Your Skills to the Next Level

mastering-functions
I'm on the verge of finishing a great course called "Clean Code" by Maximilian Schwarzmüller.

I stumbled upon the concept of writing good and clean functions and wanted to share some valuable principles which will be especially handy for beginners. So you can see this blog post as an informative summary of that course section.

Let's dive in by looking at eight main points:

  1. Functions are like little helpers in our code that we can repeatedly use to do something specific.

  2. A good function should only do one thing. It shouldn't be trying to do too much all at once.

  3. We can also think about levels of abstraction, which means how high or low we are in terms of how much detail we deal with.

  4. High-level operations are like big-picture ideas that we can express with a few words or phrases, while low-level operations are more detailed and specific.

  5. A good function should only be responsible for work that is one level of abstraction below its name. This means that if the function has a descriptive name, it should only deal with operations that are one level more detailed than that name suggests. Use verbs or short phrases with adjectives to name functions correctly (e.g., send_data)

  6. When we write a function, we should give it a descriptive name that tells us what it does.

  7. If a function is doing too much, we can break it down into smaller functions that each does one specific thing.

  8. By breaking down functions into smaller pieces, we can make our code easier to understand and maintain.

Consider this simple function that calls collect_coin and adds 1 to the player's coin count.:

def collect_coin(player: dict) -> None:
    player['coins'] += 1

Enter fullscreen mode Exit fullscreen mode

Here's an example of a lousy function that's trying to do too much:

def play_game(player: dict, enemies: list, walls: list) -> None:
    for enemy in enemies:
        if player['rect'].colliderect(enemy['rect']):
            player['hitpoints'] -= 1
            if player['hitpoints'] == 0:
                player['game_over']()
    for wall in walls:
        if player['rect'].colliderect(wall['rect']):
            player['move_back']()
    player['coins'] += 1

Enter fullscreen mode Exit fullscreen mode

The function calls play_game, which checks for collisions with enemies and walls, adjusts the player's hitpoints and coin count, and even ends the game if the player's hitpoints reach zero.

To illustrate, we can fix the play_game function by breaking it down into smaller functions that each does one specific thing.

def check_for_enemy_collision(player: dict, enemies: list) -> None:
    for enemy in enemies:
        if player['rect'].colliderect(enemy['rect']):
            player['hitpoints'] -= 1
            if player['hitpoints'] == 0:
                player['game_over']()

def check_for_wall_collision(player: dict, walls: list) -> None:
    for wall in walls:
        if player['rect'].colliderect(wall['rect']):
            player['move_back']()

def collect_coin(player: dict) -> None:
    player['coins'] += 1

def play_game(player: dict, enemies: list, walls: list) -> None:
    check_for_enemy_collision(player, enemies)
    check_for_wall_collision(player, walls)
    collect_coin(player)
Enter fullscreen mode Exit fullscreen mode

Side Note:

rect and colliderect are attributes and methods of a Rect object, which is a built-in class in the pygame module used for handling rectangular areas.

So, the expression player.rect.colliderect(enemy.rect) checks if the player is hitting the enemy by comparing the position and size of the two objects using the colliderect method.

Top comments (6)

Collapse
 
tracygjg profile image
Tracy Gilmore

Hi Max, I really like your post, it contains some sound advice.
One lesson I think we can take from the Functional Programming world is to "keep functions pure". Try to restrict functions to effecting only the data it is passed as parameters to avoid side-effects and make them more testable.
Regards, Tracy

Collapse
 
xshapira profile image
Max Shapira

Thanks, Tracy! Glad you found it helpful.

Collapse
 
cjsmocjsmo profile image
Charlie J Smotherman

For me I could care less about how beautiful or clean the code is, I'm more concerned with, does the code do what it's suppose to do and how fast does it do it. I would rather have ugly hideous looking code that is blistering fast, over beautiful clean code that is clunky and slow.

Beauty or Cleanness of code is in the eyes of the beholder.

Collapse
 
pri86 profile image
Paul Ritter

What's the point of blistering fast code if the next dev needs a week to understand it in its hideous glory and then adds x bugs while changing it. Development is a team effort, you keep the code clean not for aesthetic reasons but for your colleagues.

Collapse
 
cjsmocjsmo profile image
Charlie J Smotherman

Whats the point of clean code if your employer (or your own company) can't stay in business because everyone is flocking to the competition because their program runs faster?

Comments are your friend.

Not all development happens in a team setting.

Collapse
 
tksoh profile image
TK Soh

It seems to me that the original play_game() just need a bit of adequate comments, which is sadly missing even after breaking down into multiple functions.