Functional composition & the creation of the “Business Objects” for your project.

Elias Martinez
The Startup
Published in
7 min readOct 30, 2020

There is one thing in Javascript (or any functional programming language) I consider any OOP envy how easy is to implement, Javascript can be criticized, they can laugh at being the only language with a monster book describing the whole language but with a tiny one only telling you the “good parts”. but real easy composition they will never have it.

The simplicity of it is kind of pure art. we can take one object and convert it into whatever we want him to do by adding behaviors we want even at runtime with just a few lines; that is something they would only dream on build objects with behaviors on the fly. I will be talking with code but first, let’s be clear what a business object I will refer to.

The “Business objects”

That piece of the code with attributes and behaviors represented in the shape of “classes”.

Once they are defined they become a kind of written in stone rules that hardly can be changed, they acquire attributes and behaviors but the reality is that they can mutate over time (and sometimes over the runtime), changes that depend on the client/business needs, (even sometimes the humor). What we do now? we go back to the class to re-define it so we add those behaviors or decorate the classes.

Sometimes we have identical behaviors between totally different objects such as there is no way that inheritance can save us; so duplication comes to the rescue. don’t you feel dirty after having to duplicate the functionality?.

Let's show a silly example of a "real estate domain"Property
- contacts: CompanyContact[] <- agencies or brokers representatives
- purposes: Purpose[] <- can be an office, retail, industrial, etc...
- amenities: Amenity[] <- pool, gym, metro access, parking, etc...
Availability
- PropertyRef: Property
- contacts: CompanyContact[]
Photo by Joshua Ness on Unsplash

Here we have Property, and a property can be a building, it can be a land property and hold a variety of attributes. Meanwhile, Availability is a physical space that exists in a property. Both have contacts (in real estate you have people representing the buildings but not one of its availabilities, even doe one availability is IN the property, the set of contacts can be completely different), they have the same functionality but we can’t just inherit the behaviors. we don’t want to inherit amenities and the other stuff. I might want to have a Purpose but not all, an Availability can have only one Purpose (at least for this imaginary real estate company it works like that) either you are an office or a restaurant right?.

Where are my “lego bricks”

Here is where composition comes to the rescue. If instead of defining a set of rigid classes you define bricks of attributes & behaviors that can build and adapt to any data/business model is gonna be easier to deal with. I want to do a parenthesis and being honest as well. I’m not saying this is a panacea, be conscious that also this process to well define your bricks is hard, is thought and as defining classes will define the course of your application and it’s limitations but I truly believe this is way easier than and help to reduce the amount of code you write.

Photo by James Pond on Unsplash

Here they are (the lego bricks)

Let’s start with some start of initial point with business code involved and we will see how we can start improving it:

See repl.it here

Now we can’t just stop there

We are now enabled to just make more lego pieces, let’s start with something “silly” but useful. we’ll start with a safe iterator, we see many x || [] so let’s make it a base function

what a silly sample right?. let’s continue. We find many times to have flagged elements as primary things right? well, then let’s make a primary selector factory:

It’s a simple curried function, we create a function that receives a couple of attributes, 1st where we have to look (a collection name basically), 2nd what to look for(attribute name), then we return a function that later will receive a state to which we will apply the search for the “primary thing”;

Also notice we already started using the `safeIter`.

With this in place, we can build our first compose-able thing for “primary purposes”.

Now for contacts, let’s assume that in the contacts array we have items like:

We can’t use hasPrimaryPurpose first because is not under purposes and second because it does not have the primary column, therefore we need to create another factory.

We started granulating business logic. Now, remember we said purposes has also their own contacts inside?, well if they keep the same structure, we can now reuse our hasPrimaryContact composed function. We are now in the first stages, we can just only go further.

Another example, I’m pretty sure you already noticed too much duplication on CRUD operators; let’s do something there, this is gonna be thought so prepare your sharpness.

We need to know first the outcome function we need to provide to the top composers (PropertyFactory, AvailabilityFactory) if we look at the shape of the delete operator.

The first thing we see is, we need to produce a function that receives a “target” object (in the above sample is “purpose”)

having this, we can start generating more composers, based on different preset/common criteria's we have in your application, like delete by id, or delete by name, or delete by type or delete by whatever the heck you want.

see what I mean:

I think you get the point, every single “brick” function or composer function(whatever you name it) plays a role and can help you out from simple to complex stuff and all depends entirely on you and your sharpness sense.

Last thing but not less important you have to worry about is how are you going to organize your stuff

utils/
|--safeIter.js
|--byFieldComparator.js
bricks/
|--deleteById.js
|--deleteByName.js
|--hasPrimary.js
|--setAsPrimary.js
factories/
|--addElementsFactory.js
|--deleteElementsFactory.js
|--createDeleteFactory.js // or you can combine them.
|--filterElements.js
|--hasPrimaryFactory.js
|--markAsPrimaryFactory.js
business/
|--commons/
|--addContact.js
|--deleteContat.js
|--deleteTenantContacts.js
property/
|--PropertyFactory.js
amenity/
|--AvailabilityFactory.js
tenants/
|--TentantFactory.js

Conclusion

I know this is a silly example but I tried to explain the basis on how incrementally you can build your bricks and build as complex/crazy business logic your application might need to create entities and how they relate to each other.

Imagine you build the objects based on a dynamic input where you define the set available rules/behaviors and based on the input you on the fly (yes at runtime) you build and prepare objects with the behaviors you need/want. this is a good approach to fix the problem of the gorilla banana (at the level of business objects of course).

I took inspiration from Mattias Petter Johansson (which BTW I miss fff), where he mentions more or less the next example: imagine just to say something a mobile game:

Client: — What if I want a dog character.
Dev: — ok I have a dog factory.
Client: — oh!, also I want a robot.
Dev: — ok I can have a robot factory yes.
Client: — can it clean?
Dev: — for sure I do also have a cleaner factory.
Client: — you know what could be cool, if I want a robot dog cleaner.

Dev: mmm…

Photo by Nastya Dulhiier on Unsplash

Here is where OOP get’s problems you might end up having a `barking-robot-cleaner` that also does poop.

Whereas with composition you can build exactly what you want that does the exact things you want do do, if you have bricks for each individuality behaviors like, robot factory + cleaner factory + barker factory. Then you can get what you want, a robot-clenaer-barker (no pooping). I do agree OOP has composition too but have you seen how hard and ceremonial it is? and if you don’t do it well you still may end-up injecting things you don’t want to have available there.

The big but on this is the fact that how to organize things around is up to every developer can become messy if we don’t do right choices (there is no standard guide other than the usual hints of keeping this related next to each other or categorize them by domain or try to convey with DDD); So well documentation is important and needed to let other devs/contributors know what “bricks” are being offered and what they can do for them.

In the end, it’s a matter of preferences, It’s up to you… but functional programming is better.

--

--