Applications are Components (AKA Microservices in Elixir)

From @pragdave’s latest blog post:

Thoughts/opinions?

I personally like the idea of building an app as a series of ‘components’…


Edit: Check out my post here - it seems Dave was actually on about something more akin to Microservices…

4 Likes

Honestly, I’ve been thinking a lot of the same. Then I think, is it actually too much?
I mean, I want to be pragmatic. Where is it pragmatic to draw those lines?

Though, I almost always have a separate application for business logic. My web application is a presentation, authentication, and maybe authorization. Then yeah, I have things like Users is its own application.

If I have a real-time in memory state then I probably have a Persistence application that subscribes to some kind of state change emitter to write to a database in the background.

And why do you have contexts in the web layer?

I’m guessing this is instead of each context having it’s own application. In which case it is just pragmatism. I am already just using this for presentation and authentication, breaking it out seems like a chore rather than a boon.

If it’s just any contexts in general, then I would say because Threads are a different context than Profiles. A web context may have it’s own business application or may share one with another context.

Anyway, that’s just my two cents. Probably a little bit long winded though.

1 Like

way to develop and deliver software. It is way stronger than deployment
in other languages. Again, with erlang, it is not what people are used
to and it may not work great with existing tooling but the reason is
they were way ahead of the other languages and choose a different (imho
better) path. This goes not for basically everything in erlang. It walks
its own way and you may have to re-think what you are used to to
leverage this.

To comment on what dave said (I’ve quoted things in order of when they
appear in the quote but they should’ve likely been re-ordered to make
more sense).

they really weren’t that good at naming things.

Cmon, with applications like mnesia, et, gs, ic, the naming is great!

One of the most confusing names is application.

I think application is the correct meaning. And looking and the examples
above I don’t think “application” even make it to the list of confusing
names.

The only reason for confusion but I think it is because they are used to
terminology from other languages and development environments.

The BEAM is the operating system. An application is a stand-alone unit
which can be started/stopped independently in the OS. They can be
individually upgraded, installed and removed.

In the same line we should then stop calling processes ‘processes’
because it is confusing. They are not processes but co-routines/green
threads or what-ever other terminology you can come up with.

Erlang applications are really just components.

Are the really just components? What is a component? A replacable,
configurable unit? But does it even make sense to start/stop a component?

I think “applications” is more common in erlang than in elixir as I have
a feeling erlang releases was a bit overlooked initially in elixir and I
have seen here on the mailing list that people prefer to include “other
libraries” as part of their own supervision tree rather than running it
as a stand-alone application, and they (I don’t even know I mean with they
here) ship “applications” as only
libraries (but they don’t use library applications (doesn’t make sense
to me)).

I think this is because people aren’t keen on the more static,
not-configured-the-usual-way of erlang releases/applications. And they
provide their own configuration. I see this happening much more in
elixir than other beam languages, probably because people expect certain
things from tooling and if it is not working the way they expect they
tend not to adopt it.

Elixir is likely good for adoption for the BEAM but they also walk away
slightly from the conventional way of doing things which tends to really
well thought-out but “different” from what you are used to.

The Logger, for example,
is an application. The Elixir compiler contains over a dozen.

The logger makes sense as application. You operating system have one as
well (syslog).

Other examples of more “complete” applications are mnesia, dialyzer,
diameter, observer, inets/{ftp,httpc,httpd,tftp}

Then we have “library applications” which I think is almost completely
dropped from elixir. I.e an application you include which doesn’t have a
supervision tree. It is more like the conventional library in other
applications.

There are also ‘included applications’ which may make a lot of sense
but for some reason had a bad reputation both in erlang and elixir
world. An included application is an OTP application which you are
responsible for starting/stopping and which runs in your own supervision
tree. The only “rule” I guess for an embedded application is that it
should only be used in the end release and they should never be used if
you want to re-use a component in another release/application.

So I’m trying to retrain my brain by writing my code as series of separate
applications, each as small as I can make it. A

Good advice. Again, cohesion and decoupling is what is needed. Generally
if something can stand on its own and it has high cohesion then making a
separate OTP application from it makes sense.

Somethings you can use OTP applications to just separate concerns in
your release too. Then you can cheat a little bit on cohesion and have
OTP applications in your umbrella app to be a little bit more dependent
on each other and the reason you have them running as separate
applications is for fault-tolerance and development modularasation.

Enough of the rambling. Please read:

http://erlang.org/doc/design_principles/users_guide.html

It is a great resource to really understand erlang and it will make you
use the resources available in a better way.

1 Like

Unfortunately the term component has been beaten to death - into absolute meaninglessness. Look at stuff like UML Basics: The component diagram. And from what I recall people were just as confused about components back then as they are confused about context’s right now.

They are called “OTP applications” - typically only shorted to “Application” if it has already been firmly established that the setting is “OTP”.

If pressed for an alternate term I’d be inclined to call them “modular services” (not that service hasn’t been beaten to death either) - which according to José run lots of nanoservices.

1 Like

Decoupling things in different applications might make sense if you have the need/usecase for them, but I’d argue there are also cases where it’s “preemptive optimization”. As soon as you business logic is no longer contained in a single unit you have to deal with the potential of changes getting out of sync and things like deployment and version control won’t get easier as well. To start with I’d only strive to decouple things in a reasonable way within a single application; only splitting up code in separate applications if it’s worth the drawbacks. Like for example if parts of your code are really just library code without ties to any business specifics, then you can surely split it out. But I’d advice not doing it just for the sake of it.

1 Like

Joe Armstrong actually agrees with Dave:

You’re right about applications - badly named - we should have called them components.

For me components are just parts of something. So for instance, I might have a registration component, an authentication component, a profile component, a forum component, etc.

When Volt was on the scene, its components were very well received.

Personally I love the idea of being able to build an app by a series of components, not only would it make maintaining the app easier, but help when building the app too - as you have goals (components) you can tick of your list. An added benefit is that it makes it easier to share components with others or for your own apps too.

1 Like

Entirely true.

Each Application should just be a communicable component of the overall System.

And yep, that is entirely how I see it, as the BEAM being a kind of OS, with Processes on top of it, an Application can spawn many Processes, etc…

Also too true…

1 Like

It’s nice that that’s how it works under the hood, but we’re creating apps, so (for me anyway) it makes sense to view an app as an application but with several parts to it:

–App
—Component 1
—Component 2
—Component 3
—Component 4

Well, that’s all fine - you just have to manage expectations very carefully because lots of people will have a pre-conceived notion of what properties a “component” embodies:

One issue is size - there are small OTP applications - but there are also large ones (whether that’s a good idea is a separate issue). So while any OTP application is a “component” of a larger whole the size or granularity may not be a match for a large part of the audience.

For example in OO circles “components” could be as small as a class or as large as a subject but are typically found at a granularity level in between - in that space I would be more inclined to classify an OTP applications as a subsystem (which happens to coincide with component) but I couldn’t see an OTP application going down to the class level (short of a class that represents an aggregate).

The other issue is that the phrase “off-the-shelf component” has burdened the plain term “component” with the notion of being inherently reusable. The focus on the pursuit of reuse in the OO world has been a source of a lot of costly accidental complexity. “Trans-OO” replaceability has been displacing reusability more and more on multiple levels as an objective, as a means to help supporting ever changing business needs.

For Example:

###build Subdomains for Replacement Rather Than Reuse
When developing models in subdomains try and build them in isolation with replacement in mind. Keep them separated from other models, legacy code, and third party services by using clean boundaries. By coding for replacement rather than reuse you can create good enough supporting subdomains without wasting effort on perfecting them. In the future they can be replaced by off‐ the‐shelf solutions or can be rewritten as business needs change.

Patterns, Principles, and Practices of Domain-Driven Design p. 39

In conclusion I’m always reluctant to use a term that can be easily mistaken to mean something else entirely by other parties. Furthermore if I always have to explain in excruciating detail what the term means to me then in my view that term has lost its value for keeping communication effective.

1 Like

Well it seems what he was talking about is indeed something more ike Microservices.

I’m currently working my way through his new online course (which is awesome btw) and he says he likes to build his apps as lots and lots of smaller components… and at the end of the video says that if he were ‘buzzword compliant’ he’d have said they were microservices.

I guess I am surprised at how small these components are - one of them is tiny, it’s a very small program that fetches a random word from a .txt file after a series of transformations! Dictionary.random_word

I suppose you could say the clue is in the name Microservices :lol: but I guess I wasn’t expecting them to be this small!

Each component/microservice is included as a dependency in the mix file of the main app (or I guess the bigger ‘component’) with a local path or GitHub url:

  defp deps do
    [
			{ :dictionary, path: "../dictionary" },
		]
  end

He mentions that if what you’re working on can be used elsewhere, it makes sense to make it a separate mix app/componant like this.


This is really interesting, particularly how they all connect to each other in an Elixir app (a very simple dependency).

I’m quite excited about this :lol:

How does this fit in with how you all are writing apps?

4 Likes

I’m doing something similar in my code - though nothing is quite one file tiny! Big pluses are organization and clear one-way dependencies.

It also lets me wrap up code that could conceivably be released as an open source library. I’ve only released one so far (Kronky), but there are three other candidates that I may release when I have time. I’ve got CEO approval and it’s a nice way to give back to the community.

I also assume that having different applications in my umbrella “magically” (aka I don’t really grok all the OTP stuff yet) makes my code more concurrent. For example, anything that touches an outside api is it’s own app. So it has it’s own supervisor and processes and so forth which is good? More, shorter lived processes > Fewer, long lived processes afaik.

2 Likes