Cloud Parts

Object-oriented, functional or service layer?

DimensionObject-oriented programmingFunctional programmingService layer
In one lineObjects that own their data and the methods allowed to change itPure functions that turn immutable values into new valuesStateless services that run each use case over plain data objects
Where state livesInside objects, in private fields changed only by their methodsIn immutable values passed from function to function; real changes are pushed to the edgesIn the database and in plain data objects loaded per request; services keep none
Where behaviour livesIn methods on the object that owns the dataIn standalone functions that take data and return dataIn service methods, one per use case, between controllers and repositories
How variation is handledSeveral classes behind one interface, picked at run time (dynamic dispatch); subclasses, used sparinglyPass a different function in; branch over the shapes a value can takeInject a different implementation of an interface through the constructor
TestingPut the object into the right state, call methods, check the result; mock its collaboratorsCall with inputs and compare the output; no setup and no mocks for the pure corePass fakes for repositories and gateways to the constructor
ConcurrencyShared mutable objects need locks or must stay on one thread; Kay’s message-passing objects avoid that, like actorsImmutable data can be shared freely; parallel pipelines are safe when the functions are pureServices hold nothing, so you run more copies; the database transaction handles conflicts
Typical languages and frameworksJava, C#, C++, Python, Smalltalk, TypeScript classes; Go’s interfaces without a type hierarchyHaskell, OCaml, F#; the same style in JavaScript, Java streams, Rust iterators and ReactSpring (@Service), NestJS (@Injectable), ASP.NET Core, Rails service objects
Common failure modeDeep inheritance trees and a noun for every verb (AbstractProxyMediator)Dense chains nobody can read, hidden copying costs, effects leaking into “pure” codeAll rules in fat services over bags of getters and setters (the anemic domain model)
Pick it whenLong-lived things with rules to protect, and many variants behind one interfaceCalculations, transformations and rules you want to test easily and run in parallelBusiness backends with several entry points, on a framework that already expects it

Rule of thumb

These aren’t rival camps; most real backends use all three. A common, healthy mix: a service layer as the entry point for each use case, domain objects that guard their own rules, and pure functions for the calculations in between. Reach for objects where state has rules, functions where data flows, and services where a request has to be coordinated across a database, payments and email.

Sources