Published on

Software Engineering for busy parents


Being lost

Is there a new framework or a library that draws attention of entire community, but the only thing you made is reading a tweet about it?

Did you, during the conversation, hear htmx, but you thought someone made mistake and should say html?

Have you been late with using new C#11 "double bang" operator, because it got rejected before you even learned about it?

Welcome to the club of busy people!

What is the meaning of life?

Of course, I don't mean life life - I am talking about your, mine, professional life.

Are we dopamine-driven, technology-fueled creatures, enchanted in a human body?

There's also "after life". Life after professional life, where babies are crying, you are tired and your back hurts.

Still, as software engineering professionals, we would like to be up to date with the coolest and the newest stuff.

Is there a lighthouse of knowledge, showing the direction for ships having various stops during the day?

It is not about k8s or microservices

I don't want to look as if I am demonizing or devaluating either k8s or microservices. They are applicable to set of problems, but in other scenarios might be pretty cumbersome.

Technologies get outdated.

Ideas, concepts and fundamentals preserve.

It's nothing new, or even fancy.

Might be that some of the new, sexy toys materialize some "old", well-explored concepts, because finally we arrived at the moment of time when it is technologically possible to bring them to live.

On the other hand, innovation happens not in the vacuum, but rather by mixing up experience, incubated ideas, stories and patterns. Such amalgamation produce a graph of things connected in the new, creative way.

Nevertheless, coming up with so-called "Maxwell equations", discovering "Foucault's current" or imagining "Theory of relativity", were not invented in the single night.

They might appear as an final, read-model state, but actually it was a process full of consequitive events, leading to the final event of breakthrough.

Programming is fun

You might call me naive, but recently I am getting more and more aware that "coding" is a teeny-tiny droplet of entire endeavour.

Maybe it is because of not having that much spare time for it as I would wish for.

It is fun to build, to make, to create, to feel "the zone" and get lost of one's ego in a pure bliss of creation.

But is it the only thing that constitutes "Software Engineering"?

I really love the first sentence of the book Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development:

Conclusion 🔍

Programming is fun, but developing high quality software is hard.

We can't just develop, we need to embrace what is known for so long time - it should be "doable" by standing on the shoulders' of giants.

Software Engineering for busy parents

Of course, you might not be a busy parent and still benefit from battle-tested, "old" observations about Software Engineering.

There are various concepts, patterns or approaches I find particurarly interesting. Most of them I learned either from courses, books, articles, videos or from production experience.

What is great about them? It is the fact that one can use it agnostic to the technology. They are not subjects of changes, at least not so frequently.

The stability of their wisdom is the key here.

They might be considered as "general problem solving skills".

Let me channel them in the form of text, for you, my dear Reader!

1. Focus on the problem, forget the programming part

We, developers, tend to jump to sketching or prototyping the solution almost immediately.

It is so easy to open editor and draft couple of classes (which turn out to have no responsibility and be simple POCOs - there will be separate blog post about it soon!).

I learned two fundamental, analytical questions that I am trying to use on every problem I try to solve:

  • What is the problem I am currently solving?
  • What is the problem I am not currently solving?

They both try to help on finding the true nature of the case we are working on, counteracting on so-called The XY Problem.

For example, when you try to fix a bug, don't refactor code at the same time. It is well-known from TDD approach, especially when doing verification through tests (Would you like to get mine perspective on it? Please check "The ambiguity" of TDD).

But both questions apply well to such scenario, namely:

  • "What is the problem I am currently solving?" - fixing a bug
  • "What is the problem I am not currently solving?" - refactoring ugly code.

How can you utilize those questions in scenario, you are/were/will be working on?

2. "Two weeks of development can save you 15 minutes of analysis"

The first time I've heard this phrase from Sławek Sobótka in one of his talks.

It's self-describing - in most of the cases spending time on understanding the problem might bring enormous benefits.

You either save time (meaning money) by modelling correct solution OR by not spending time on corrupted/broken/wrong model.

Next time, even when working on a feature that "seems simple", try to think of it a bit more deeply, setting aside a 15 minutes.

3. Validating usefulness of your model/solution

Imagine we did a short analysis and it seems we understand the problem quite well.

After a brief thinking we have the solution. We start implementing it and soon it we are drowning in complexity. Do you know that feeling?

Seems like we are missing critical thinking about our solution.

I find a set of two questions working perfectly to achieve so:

  • For the given context, what problem X solves?
  • For the given context, what problem X brings?

Where X is your approach/model/solution/idea.

They appear as so stupidly obvious that I believe we often do not use them consciously. I learned about them in Legacy Fighter (only in Polish 😔) training.

I adore them so much!

We can use them for new method, responsibilities assignment, finding trade-offs, assessing new tool or thinking if a given architecture fits our needs.

They might be known as "apply the right tool for the right job".

For instance, we need to have two bigger capabilities, A and B. We consider using either modular monolith or seperately deployable services (I am avoiding talking about microservices, because previously I said it is not about them so I need to keep my opinion, right?) to support them. Just to add more details, we are small team and capability B might require integration with legacy (mhm, I should say core product?).

And now:

  • For the given context, what problem(s) modular monolith solves?
  • For the given context, what problem(s) modular monolith brings?
  • For the given context, what problem(s) seperately deployable services solve?
  • For the given context, what problem(s) seperately deployable services bring?

Nice, isn't it?

4. Watch your boundaries, capture concepts

I couldn't forget mentioning Domain-Driven Design.

I am not talking only about "tactical" parts of it, but also about "soft"-ish parts, which might be considered "strategic".

Thinking contextually, carefully observing the language used, and finally looking for a model bounding domain language (which relates to a contextual world, a perspective) - true fundamentals, keeping their validity in most of the times.

It is also about reasonably capturing the concepts your domain consists of.

Not using only strings, collections or doubles, but building meaningful stories that live inside of your problem space. (What I am talking about? Please see The value of Value Objects).

5. Separate the core from external world

Hexagonal Architecture, Onion Architecture, Ports & Adapters Architecture, Clean Architecture, The Functional Core and Imperative Shell - you name it.

I firmly believe that all mentioned constitute the same principle - isolate your logic from effects.

On the bigger level we can think of architecture, but in the smaller scale you can think of a simple class or a function.

Yes, it might be related to "Single Responsibility Principle", because it is all about responsibilities assignment.

To achieve such thinking, I like to visualize how people would collaborate within an organization.

Then it becomes clear who knows what should be the decision and who knows how to react upon such information.

6. Do not start with the persistence - three aspects of modeling

Again, heard about it in Legacy Fighter and Better Software Design podcast.

Originally, it is presented in the book Rethinking Systems Analysis and General Thinking by Gerald Weinberg.

I am talking about so-called three aspects of modeling:

  • Being
  • Behaving
  • Becoming

Each of those aspects is related to a specific set of questions that might be used to bring deeper undestanding and clarity.

Whereas we typically start thinking about "Being" aspect - the structure, the data, the properties, it might be beneficial to find proper usages, behaviors and responsiblities.

Then looking for a specific set of details, that are required to satisfy such operations, completes the entire design.

This approach totally shifts one's mind for modeling - from data-first (producing bag of properties) to behavior-first (promoting collaborators with proper responsibilities).

7. The Ying-Yang of Software Engineering

Cohesion and coupling.

Coupling and cohesion.

There were a lot of tweetscussions regarding this pair recently.

Again, they are applicable to variety of problems, levels nad environments.

Either looking at the boundaries of your services or designing a proper structure of React components - consciously or subsconsciously we make a decisions about amount of coupling and how cohesive our constructs will be.

At the moment of writing, I think that both of them give birth to responsibilities assignments, contextual thinking and many more of the patterns that were discovered/invtented during the history of Software Engineering.

Never ending story

I think I could mention more books, approaches and observations, but I hope you see the point.

There are topics and areas, while being technology agnostic, open a new world of understanding and self-development.

We don't need to foolishly pursue never ending stream of new shiny things, because there are stable concepts, tools and fundamentals we can bet on.

I know that it is not a "complete" list, but still it brings the conclusion that it makes sense to revisit the basics, because they are the most difficult part of our job.