Why programs ARE algorithms, but not like the ones in interviews
Tags: programming, essay
Published: 2021-12-03 14:36:13

---
title: Why programs ARE algorithms, but not like the ones in interviews
published: true
date: 2021-12-03 14:35:15 UTC
tags: programming,essay
canonical_url: https://siderite.dev/blog/why-programs-algorithms-but-not-like-ones-in-inter/
---

Original post at: https://siderite.dev/blog/why-programs-algorithms-but-not-like-ones-in-inter/

## Intro

When learning to code we get to these exercises and tests and katas and interview questions using some array and expecting some magical string or number and you hear they are called algorithms. And they are intellectual, complex, mathematical, abstract, annoying and feel completely random. But when you are actually doing something real, code doesn't look like that at all. It took me years to understand what the problem is and I am going to share that with you today.

The short version is this: If your program **logic** doesn't look like an algorithm you are probably doing something wrong. Programming katas are simple because they need to be able to check your answers and give an unequivocal result. It's good to know them, but you shouldn't **need** to know them, because they are not meant for the real world, but for controlled short term experiments. Unless you are going to work for a sorting company, that's a thing.

Now for the long version.

## What you expected versus what you get

You get your first job as a developer and your tasks sound like "_fix the color of the submit button_" and "_the report page shows title in the right, move it to the left_". And you think "_why the hell did I go through those manual [Bubble sort](https://en.wikipedia.org/wiki/Bubble_sort "simple sorting algorithm that repeatedly steps through the list, compares adjacent elements and swaps them if they are in the wrong order.") algorithms and learned [Quicksort](https://en.wikipedia.org/wiki/Quicksort "a divide-and-conquer algorithm that works by selecting a 'pivot' element from the array and partitioning the other elements into two sub-arrays, according to whether they are less than or greater than the pivot.") partitions if this is what programming looks like?!_". The answer is that you will get to a point where your skills will make people feel confident enough to let you design and architect the things you write. Only then the algorithmic thinking will help because you will have decided yourself what the button does and why its color or position are what they are.

When you start designing flows and entire systems and how they click together it helps a lot to see a component as an algorithm: **inputs, rules and outputs**. "_But, Siderite, a button is not either of those!_" you will say. And that is true, but also completely irrelevant. Your program **logic** should not care about a button, but about an input. And now you also see why the summing of distinct array items is a poor substitute for real life problems, because a click on a button is not a value in a properly contained list, but an event. And most programming exercises and even entire computer classes don't treat events as abstract inputs at all.

Lately this has started to change, both in how programming languages look at actions and events as [first-class citizens](https://en.wikipedia.org/wiki/First-class_citizen "entity which supports all the operations generally available to other entities. These operations typically include being passed as an argument, returned from a function, modified, and assigned to a variable"), but also in theoretical and programmatic concepts like [observables](https://en.wikipedia.org/wiki/Observer_pattern "an object, named the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods."), [streams](https://en.wikipedia.org/wiki/Stream_(computing) "a sequence of data elements made available over time"), [functional programming](https://en.wikipedia.org/wiki/Functional_programming "a programming paradigm where programs are constructed by applying and composing functions. It is a declarative programming paradigm in which function definitions are trees of expressions that map values to other values, rather than a sequence of imperative statements which update the running state of the program."), [reactivity](https://en.wikipedia.org/wiki/Reactive_programming "a declarative programming paradigm concerned with data streams and the propagation of change. With this paradigm, it's possible to express static (e.g., arrays) or dynamic (e.g., event emitters) data streams with ease, and also communicate that an inferred dependency within the associated execution model exists, which facilitates the automatic propagation of the changed data flow."), [event buses and messaging](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern "a messaging pattern where senders of messages, called publishers, do not program the messages to be sent directly to specific receivers, called subscribers, but instead categorize published messages into classes without knowledge of which subscribers, if any, there may be. Similarly, subscribers express interest in one or more classes and only receive messages that are of interest, without knowledge of which publishers, if any, there are."), [microservices](https://en.wikipedia.org/wiki/Microservices "a variant of the service-oriented architecture (SOA) structural style – arranges an application as a collection of loosely-coupled services."), etc. It makes sense to not quite get it when you have not begun to touch these concepts and when everybody and their grandmother focus on the latest frontend framework, rapid application dev tools or extensions to VS Code, but at their very core all of these things are solutions to the same problem, following the same principles.

## Breaking reality apart

As you start to climb toward seniority (and that does NOT mean going to Mexico so they call you "señor developer") you learn about [Separation of Concerns](https://en.wikipedia.org/wiki/Separation_of_concerns "a design principle for separating a computer program into distinct sections. Each section addresses a separate concern, a set of information that affects the code of a computer program."), as a good strategy to isolate changes, improve readability and testing and ease maintainability and deployment. You learn about writing applications in [layers](https://en.wikipedia.org/wiki/Multitier_architecture "a client–server architecture in which presentation, application processing and data management functions are physically separated"): the UI, the business logic, the database access, etc, which is also about separating concerns. And as you go further and further on that path you realize...

_ **Wait! This business logic thing looks like an algorithm! It abstracts all of its dependencies until all that remains is: inputs, rules, outputs.** _

But there are things to confound you: events, user input, parallel tasks, race conditions, heavy load use, **the cloud**. You can use the same tools, though! Abstract everything, separate concerns. What is an event but a signal coming from a source? Your input is the observable source object and the events themselves just values coming in. Or just a method that receives an event object and you handle sending the event someplace else. Everything coming from the user can be handled the same way. Concurrency is solved by maintaining as little internal state as possible and, when absolutely necessary, guarding it against concurrent access via clear established methods, like semaphores and transaction contexts.

Once your logic is clear, your data structured and every external dependency abstracted away, you can run and test every subsystem in isolation. You don't care something is supposed to be a click, or an error, or a network message or on Windows or Linux or how it's deployed or if the database is available and what kind it is, what UI is being used and what it does, where in the world you are and what time it is and so on. Your code is now an algorithm: a set of rules applied on predictable input which can then be tested for an expected output.

A new requirement comes: you change just the part responsible for the requirement. You can write unit tests before or after or test it manually without caring about anything outside that piece of code. A bug is reported: you write a test that reproduces the bug, you change the code, see the test pass and you never had to open a browser or an app or go to some external environment or ask some other team for user access or if you can use the database. How does it sound to be able to code without ever having to manually go through application scenarios?

Of course there will be an ugly user facing piece of code that you will have to write, but it should be minimal. Your logic is sound, almost mathematically provable to be correct, and how you plug it in is irrelevant. Yes, you will have to work with the graphical designer in your team and make it so the nicely colored card slides across the screen, but that is a meaningless process that you play with in complete isolation from your logic. End to end testing is sometimes necessary, but it's a human thing to do, as well. Just check the "feel" of things, how they look, how they move, if it works for you. The only reason why you are going through it is because you have not been able to completely abstract the end user, with their stupid requests and complicated needs and ideas of what beautiful means.

Yet that is beginning to change as well. Artificial Intelligence, of all things, has advanced so far that you can create minimal interfaces using human language requests. "_Build me a web page with a list of items that can be scrolled and selected to be displayed in a details pane on the right_". I can imagine this can be used in real life only when the logic of the application has already been written and one is able to just plug and play such a monstrosity without much effort, while also being prepared to change the requirements, recreate the entire things in a different way, but plug it in the same.

And there will be some sort of deployment framework, with people deploying stuff and checking stuff, with data in databases or other persistence mediums. Your code logic? Doesn't care.

## Imposter syndrome

Does this sound like a pipe dream that a snake oil peddler is trying to sell you? Let me tell you that the only reason you are not working like that now is because someone though it was too complicated and decided to cut corners. And they have been paying for it ever since, as well as you.

The only proven way of solving complex problems is [Divide and Rule](https://en.wikipedia.org/wiki/Divide_and_rule "Rule! Rrrrule! RRRrrrrule! Huh huh hmm!"). Life is complex and real problems, too. Separation of Concerns, [Inversion of Control](https://en.wikipedia.org/wiki/Inversion_of_control "in traditional programming, the custom code that expresses the purpose of the program calls into reusable libraries to take care of generic tasks, but with inversion of control, it is the framework that calls into the custom, or task-specific, code."), [Domain Boundaries](https://en.wikipedia.org/wiki/Domain-driven_design "ntities/aggregate roots as receivers of commands/method invocations, the encapsulation of state within foremost aggregate roots, and on a higher architectural level, bounded contexts.") are the tools you use to break any problem into smaller manageable pieces. And that brings us back to interview questions and pointless algorithms.

When you go to a code test, **you** are the algorithm. They give you some input and an expected output and check to see if your internal rules are up to the task. Of course you could google for an easy solution. More than that, what kind of employee would you be if whenever the boss asked for something you would build it from scratch without seeing what others did? What hubris to believe that you could know the answer better than anyone else without even checking!

## Test succeeded

The conclusion of this stream (heh!) of consciousness is that once you realize the algorithmic nature of any problem (once you abstract every interface with reality), you can see the actual value of being proficient in writing one. You might start with sorting and fizzbuzz and other bullcrap like that, but they are just steps on a larger ladder that will eventually make sense, just like learning the letters of the alphabet prepared you to read to the end of this post. Also, if you are trying to get a job as a book editor and the HR person is asking you if you know all the letters of the alphabet, maybe you don't want to work there.

## [P.S.](https://en.wikipedia.org/wiki/Postscript "No, not PlayStation. No, not that Postscript!")

The links in this article are important, especially if you are a just beginning your journey as a developer. Check out the concepts there and learn to use them in your life, it will get a whole lot easier!