I’ve felt resistance to functional programming and to functional programmers ever since functional programming became “a thing”. While I’m disappointed by the arguments made against functional programming, I am equally (if not more) frustrated that the functional programming point of view has not evolved, leading it to be easily derided as developer religion.
It’s time to move the discussion forward. Because no matter our views on functional programming vs. object-oriented programming vs. whatever else, we all need to be functional engineers.
There are imperfections in the real world. We run into complexities that can’t be modeled nicely yet still need to integrate with other (sometimes poorly-designed) systems. There are constraints in resources and schedules in order to hit business goals and keep the ship afloat. We have to make the compromises necessary to deliver solutions that meet all these requirements, negotiating where possible while standing firm on critical aspects (e.g., safety must be designed in; it cannot be tested in or retrofitted).
Our compromises and firm stances need to be data-driven because engineers do not work on reactionary, baseless theories. We hypothesise and rely on quantitative evidence from our own experimentation and the experiences of our teammates. Then we must be able to communicate our findings and resulting reasoning to any audience – even a non-technical audience.
Functional engineering is more than writing code. It’s about solving real-life, real-world problems.
And speaking of non-technicals, we are always building up of set of “soft” skills and business acumen. We’ll always work with non-technical people, so it’s important to be able speak their language and apply engineering principles across other domains.
This, of course, is in addition to continuous learning on the technical side. Our field moves fast. If you rest on what you already know for too long, you’ll find that what you know isn’t nearly as valuable as it used to be.
Build with urgency and quality
I also want to address the argument against time pressure – e.g., “you can’t rush innovation”. While time pressure probably is indeed a lousy way to foster innovation, we do live in a world of fast delivery of customer-facing value. Deadlines aren’t just some arbitrary date from managers. They are driven by observing the market we operate in. Every company has competitors moving faster. Being a functional engineer means treating fast delivery and high quality as hard requirements. As if your team’s survival depended on it (spoiler alert: it does).
Let’s not dismiss this reality. Instead, let’s look at it as an opportunity to prove our strength.
Those of us who’ve been lucky enough to choose the technology stacks for their projects also need to remember the responsibility that comes with that freedom. If we don’t show improvements in delivery, it becomes harder for even the most supportive team leads to justify letting us make those choices the next time around (and I’m talking about the elephant in the room, here: mandated tech stacks).
So let’s work together to support our team leads and prove we deserve the trust they’ve placed in us.
Deliver solutions, not components
Functional programmers (and software engineers in general) like to tinker with code. But functional engineers balance perfecting the code with ensuring the overall system is delivered and maintainable.
Considering the system as a whole is not simply a matter of considering all its smaller parts. There are operational considerations, documentation, integration of all the services, migration, then finally the roll-out to customers. That’s a lot to do beyond just the coding itself. And it all needs to fit into the time between now and the delivery date.
We can do ourselves a favor by applying functional programming principles not just to the code, but to the architecture of our systems. For example, some of the work in perfecting a small microservice ends up going to waste because microservices are meant to be thrown out and rewritten if they no longer meet your needs. By contrast, applying functional concepts such as append-only stores and event-based architectures helps our efforts live much longer. This, in turn, lets us spend more energy perfecting the system as a whole, instead of rabbit-holing on individual components.
Apply the principles of functional programming (vs. “Functional Programming”)
The term “Functional Programming” means different things to different people. Some fear it, some love it, some believe they are doing it but don’t really understand it. I feel the term is getting in the way of everyone understanding that we’re all talking about the same principles.
- Immutability wherever possible. This isn’t just a Functional Programming thing. It’s a tenant of building high-performing, highly-concurrent systems.
- Less code means fewer bugs. Use available libraries over writing things ourselves not only means less code, it means more time for documentation, migration, and all the other things I mentioned above.
- Don’t repeat yourself. Find the right abstractions to reduce code duplication.
- Think of software as data transformation. Almost all software we write is mainly just reading data from somewhere, allowing code or user transformations, and then saving it somewhere else.
We should seek to apply these fundamental principles in any codebase we work with – whether using a Functional Programming language (e.g. Scala, Haskell) or not. We will all be better for it. And for the true believers among us, getting our teams to make the next step toward Functional Programming (capital F, capital P) will become easier.
At the end of the day, everyone on your team wants to deliver systems quickly with valuable functionality and as few bugs as possible. As functional engineers, we need to seek the understand the environment we work in, and deliver the whole solution to our customers.
We have lots we can do and try. So let’s get to it!
This post is featured in our ebook, “Hello World! A new grad’s guide to coding as a team” – a collection of essays designed to help new programmers succeed in a team setting.
Grab it for yourself, your team, or the new computer science graduate in your life. Even seasoned coders might learn a thing or two.