Developer Weekly Blog #1 - Programming vs. Software Engineer
Tags: softwareengineering, blog, bestpractices, diary
Published: 2023-10-02 15:18:05

This week I was reading about software engineering. I'm preparing a talk directed to university students studying this area. So the concept to my talk was directed by a primary question: what is Software Engineering anyways? The concept that I got when I was studying at the university was something like: software engineering it’s something like creating diagrams, trying to satisfy the client (because he doesn’t know what they want,) make a well structured plan and use agile methodologies.

But for the preparation of my new talk I challenged my view to the emphasis on the planning side of a project and try to focus more on the day to day side of things in software engineering that are more trickier to master than just planning an ideal thing that maybe doesn’t see the light.

So I decided to review some literature about the topic. And I found something that fit into what I wanted, a book I already knew, called: **Software Engineering at Google.** I read two chapters that I selected to prepare my topics, more specifically chapter about *what software engineering?* and *code review,* I absolutely love how developed the topics there. First of all that I need to mention about this book, contrary of what you expect this is not a book about rules written in stone, it’s more about a series of essays about topics around daily practices used by Google Engineers in their day to day life.

So this week the main ideas that I gather from my readings are:

- Programming vs Software Engineering
- Software engineering is programming integrated over time
- It’s better to upgrade your codebase in tiny beats than large scale changes
- Hyrum’s law: *“all observable behaviors on your system will be depended on by somebody”*
- Think about the trade-offs
- Code review it’s one of the more valuable things to guarantee clean and maintainable software
- Code review it’s more effective when it’s small (less than 200 lines of code) and most of the time it’s done by one person to be more efficient
- Programming it’s an individual effort and software engineering it’s a team effort

So let me explain a little bit about some of them

## Programming vs Software Engineering

There is a critical difference that you need to understand explained in the chapter *What is software engineering?* about programming and software engineering. Programming is an individual effort and software engineering is a team effort. But saying that is something simplistic, there are more aspects that you need to take into account:

| Aspect | Programming 👨‍💻 | Software Engineering 🤝 |
| --- | --- | --- |
| Number of people | It’s individual | Team effort |
| Scale | The number of lines that one person is able to write | Maybe hundreds of lines written by different teammates everyday |
| Lifespan of a project | Maybe a couple months | Years, even decades |
| External dependencies | In that short lifespan is not critical to upgrade dependencies | With time is common to need to upgrade dependencies |
| Policies | A couple of established guidelines | A lot of rules to ensure quality code and maintainability |
| Modification | Low need for modification | High need for modification |
| Maintenance | Low need for maintenance | High need for maintenance |

This table summarizes what it’s the difference between programming and software engineering, you need to think in higher lifespans, complex inter-dependencies that evolve over time and a greater scales of lines of code integrated over time. There is a quote that you need to keep in mind when talking about this: 

> _**Software Engineering is the set of policies, practices, and tools** necessary to make that code useful for as long as it needs to be used and allowing collaboration across a team_
> 

Is a delicate balance that allow teams to keep alive projects in the long run.

## Software engineering is programming integrated over time

When we are learning programming most of our projects only have a short lifespan, maybe two or four months, but in projects that will last for many years (even decades) you can’t think with the same mindset that you work when you developed these projects with shorter life.

If your project survives over time you come to realize some challenges that you didn’t imagine in the first place, with time every tiny decision has an impact on later modification and these little technical debts become a huge mortgage that you don’t know how to pay later. It is not an invitation to panic, it’s a recommendation to think about your code on a larger scale in every aspect: in time, in resource consumption or modification. Get your first guess and think of a 1.000x or 100.000x greater scale so you can see a glimpse of future problems. You don’t have to address them right away but definitely need to keep in mind to mitigate most important problems.

Maybe some examples clarify this topic:

- You’re creating validations in your app, at some point you need to validate an email for creating a user, you thought *“hmm? I just going to create a validation for this field in this section to validate this email”* but then later on you need to create the feature of editing this email but at the moment there is another teammate working on that and he re-implements a function to validate email, at the end the feature it’s uploaded and everything seems fine. Weeks later it’s created a bug mentioning that the email: myorg@company.org works fine on the user creation but not for editing, so what’s happened here? Because there are two different implementations on email validations in one it works and in another doesn’t work resulting in duplicate logic and the risk of having incoherent behavior.
- Another scenario, you imagine your application to work with a MySQL database but in some moment the people realized that there are use cases where PostgreSQL it’s better to develop new features that will be important in the future. So you now are migrating your data from MySQL to PostgreSQL but due to lack of good abstractions your code it’s tightly coupled to the original selected database so it’s going to cost more effort to be able to even start the migration process and ending writing the app from scratch.

Maybe you’re clever enough to imagine those scenarios but at some point all of us were so naive to even think that the database engine will never change.

## Think in your code in terms of clean and maintainable and not in hacky or clever

When we are working on something difficult we are attracted to using some hacky thing that we found in StackOverflow and using in our code. But later on when something else needs to change in that file you don’t even remember what was the hack about because it’s written in an incomprehensible way that now looks like a hieroglyph or some dead language no longer used by humanity.

So in those cases when something difficult exists don’t write your code in terms of something that just works, prioritize something that indicates what are the steps performed and what is the meaning of every step clearly. Luckily nowadays there is no limitation on the length of the variables or functions to write our code so we can be as expressive as we want to.

For this example I was looking for old archive of previous programs to demonstrate this point:

```python
# Code in Python
def main():
  N: int = eval(input())
  V = []

  for _ in range(N):
    C: int = eval(input())
    V.append(C)
    
  return V

if __name__ == "__main__":
  inputs = main()
  print(inputs)
```

Luckily this piece of code isn’t doing something so difficult but definitely doesn’t indicate too much about what it’s doing or the context of it. But with some rewriting reveals what was the original intention: 

```python
# Code in Python
def readScores():
  matches: int = eval(input())
  scores = []

  for _ in range(matches):
    scores.append(eval(input()))

  return scores

if __name__ == "__main__":
  scores = readScores()
  print(scores)
```

With this re-writing it’s more clear what we are doing: we are reading the scores of different matches of one user. The first section we were reading the user input to store a variable number of matches, then we read the scores and stored them in an array. The domain in which you are working it’s always useful to name things and you shouldn’t underestimate at the moment to write better code.

But is there a chance to improve even further? What if we need to read a different size of user scores repeatedly? Then maybe we can put this into a function that it’s able to read different sizes and also create a function to store the way to read user inputs:

```python
# Code in Python
def readUserInput():
  return eval(input())

def readScores(matches: int):
  scores = []

  for _ in range(matches):
    scores.append(readUserInput())

  return scores

if __name__ == "__main__":
  matches: int = readUserInput()
  scores = readScores(matches)
  print(scores) 
```

This scales even better! So you need not only to create correct code, you also need to create code that it’s understandable by others.

## Code review it’s one of the more valuable things to guarantee clean and **maintainable** software

When you have another one that review your code you’re able to get an opinion that doesn’t share your same biases, so it’s valuable to have another point of view that helps you to ensure that other people are able to understand what you write in the first place (or at least is most probable that other people are able to.)

This is another big difference between programming and software engineering, as engineering is a team effort. You count on your teammates to help you with this kind of thing and reduce our personal biases in our code and be more consistent with the style of overall code.

When doing code review it’s helpful to have this things in mind:

- Do it timely: when code review request is created try to do the review in the next 24 hours
- Be polite and professional: don’t involve personal aspects in the code review, be assertive and point out the aspects of the code that doesn’t work
- Submit small changes: in order to don’t overwhelm your reviewer do small changes (less than 200 lines of code) to the get an effective feedback
- Write good change descriptions: in the first line describe the type of change you did (bug, feature, hot fix, etc.) and why you did it. When something is not approved, change the description if necessary.

Following these directives helps you to do great code review, giving feedback to other people it’s always difficult but it’s necessary for other people and ourselves to grow. The key to give great feedback is not to involve the being (like you’re disorganized, you're a bad communicator, etc.) it’s to talk about punctual actions (like in this section the variable names are ambiguous.) So we’re always talking about something near to reality and not from our personal biases.

## Final Thoughts

The book **Software Engineering at Google** it’s a good recommendation to read if you want to grow far beyond just programming. The best thing about this book is that it’s free only to read right now, you can access it by following this [link](https://abseil.io/resources/swe-book/html/toc.html). At this moment I’m more excited to know about this because it is a problem that arises more frequently now that I’m more involved in larger codebases and I’m more confident writing code. If you want to improve in other aspects different from just writing a syntactically correct program this book is for you.