# IBM releases Elm-powered app

**URL:** <https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364>\
**Category:** Show and Tell\
**Created:** [October 30, 2018, 4:36pm UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364 "2018-10-30T16:36:49Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![vankeisb](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/vankeisb/32/1461_2.png) [@vankeisb](https://discourse.elm-lang.org/u/vankeisb)\
**Post date:** [October 30, 2018, 4:36pm UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/1 "2018-10-30T16:36:49Z")

</div>

Hi fellow Elmers,

IBM has just released Decision Composer, a free and limited offering of our Operational Decision Management (ODM - ex ILOG JRules) product.

A good portion of the front end is written in Elm, so I thought I’d share the link here, and post some feedback.

The app is live here (requires registration) :

[https://decision-composer.ibm.com](https://decision-composer.ibm.com)

It basically allows business users to model and implement complex Decisions via graphical tools and human-readable artifacts instead of code. Decisions are then compiled to executable artifacts, and deployed to runtimes for consumption in other applications/services.  
It is based on the [DMN](https://www.omg.org/spec/DMN) standard, spiced up with our own BRMS expertise.

The app is a SPA that (in short) displays a diagram, and allows to edit various artifacts in the diagram nodes, like textual rules (with syntax highlighting, code completion etc) and Decision Tables (a la XL).

![dcomp-1](https://cdck-file-uploads-canada1.s3.dualstack.ca-central-1.amazonaws.com/flex035/uploads/elm_lang/original/2X/3/372b898ac02f6d8990006751ee63b4f0e301f687.png)

Most of the app is built over existing technology and components from the ODM product. The server relies on our Java APIs for many things (parsing, validation, compilation, etc), and the front is an Elm SPA that embeds some editors written in Dojo.

In the above screenshot, for example, the Diagram is a Dojo component, with its own dom tree (and svg), and the rest of the page is Elm. Same goes for rules and tables. We use parent-child for “pages” of the app as well as for some components that are reused across the app.

# What we’ve learned

- Functional programming ! The Elm language is a good introduction to FP, especially for people with an OO background like us. Only problem :

- TEA is pretty simple to understand, people get quickly used to it. You don’t wonder where things are or should be, everything has its well-defined place. There’s one way to do things, not 50. Still :

- Elm is _really_ bullet proof, it’s not fake advertisement. We have had no runtime errors, as promised. Refactoring is easy, with the compiler telling you just about everything. And yes, really, when it compiles, it works ! Apart from the quite slow 0.18 compiler (fixed in 0.19), it’s really amazing.

- Elm can interop with “graphical” JS pretty easily. We have embedded pretty big components (like the diagram or the decision tables editor) into the Elm virtual DOM, and we interact with those through ports. It works, but :

- The build (elm make) is really simple. Compare this to your average WebPack “config”. And the UMD module can be consumed easily too : we include it into a dojo AMD layer build.

- It doesn’t require to patch your code because there’s a new release every month. We migrated from 0.17 to 0.18 pretty easily. The 0.19 migration is a bit bigger, especially because we have a few native modules, but still, it’s nothing compared to the number of updates we would have had with React+Redux+TS.

It was quite a bet when we started with Elm (0.17). Many co-workers didn’t understand. Everyone was about React back then. Even Elm’s syntax was subject to religious debates. “What ? No JSX ??? Square brackets ??”…  
Also having a big player like facebook on one side, and a weird student on the other, that didn’t help (with all my respect to you, sir Czaplicki, you are doing a fantastic job) !!

Eventually, as usual, it took some coding to convince : as soon as we started shipping things, most of the skepticism about Elm stopped.

Today, we, the developers of the app, think it’s been a good choice. The “framework” is simple and yet solid. It never really got into our way, instead it helped a lot to have this common architecture/design for everybody. We basically followed The Elm Architecture, and it worked. Of course, the app isn’t perfect, and there are many things we could do better, but it’s not because of the framework, it’s because of us, who didn’t model things correctly and stuff like that.

It took a little time to get used to Elm, especially for OO-raised people like me and most of my team. But it eventually paid off. Once you’ve understood the basic principles, you realize that coding in the browser can actually be productive, safe, and even fun.

I hope this post will help people who have problems convincing their management of using Elm, just because it’s not mainstream. Yes, you can use it for pretty complex apps, it does scale. And yes, even big companies like IBM use it !

---

<div class="post-metadata">

**Author:** ![evancz](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/evancz/32/16_2.png) [@evancz](https://discourse.elm-lang.org/u/evancz)\
**Post date:** [October 30, 2018, 6:19pm UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/2 "2018-10-30T18:19:10Z")

</div>

Thank you for sharing! This is very interesting feedback!

I have a bunch of questions, particularly about the rough spots you experienced. Knowing the particulars of your expectations and needs will be really valuable to figuring out how to make improvements strategically. I will message you soon to try to find a time to talk through things so I can make detailed notes.

Anyway, thanks again for sharing all this!

---

<div class="post-metadata">

**Author:** ![pdamoc](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/pdamoc/32/36_2.png) [@pdamoc](https://discourse.elm-lang.org/u/pdamoc)\
**Post date:** [October 31, 2018, 6:00am UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/3 "2018-10-31T06:00:42Z")

</div>

Congrats on the release!

How big is the Elm part of the app?

---

<div class="post-metadata">

**Author:** ![vankeisb](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/vankeisb/32/1461_2.png) [@vankeisb](https://discourse.elm-lang.org/u/vankeisb)\
**Post date:** [October 31, 2018, 7:54am UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/4 "2018-10-31T07:54:08Z")

</div>

cloc gives approx 45.000 lines in 170 files of Elm, including the tests.

---

<div class="post-metadata">

**Author:** ![Pilatch](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/pilatch/32/768_2.png) [@Pilatch](https://discourse.elm-lang.org/u/Pilatch)\
**Post date:** [October 31, 2018, 12:17pm UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/5 "2018-10-31T12:17:11Z")

</div>

How are you doing synchronous calls to Elm in 0.19?

---

<div class="post-metadata">

**Author:** ![vankeisb](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/vankeisb/32/1461_2.png) [@vankeisb](https://discourse.elm-lang.org/u/vankeisb)\
**Post date:** [October 31, 2018, 1:19pm UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/6 "2018-10-31T13:19:07Z")

</div>

As far as I know, you can’t.

It was an error on our part to go for Native stuff in the first place. For 0.19, I guess that we’ll migrate those native modules either to Elm code, or to ports.

---

<div class="post-metadata">

**Author:** ![Pilatch](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/pilatch/32/768_2.png) [@Pilatch](https://discourse.elm-lang.org/u/Pilatch)\
**Post date:** [October 31, 2018, 2:26pm UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/7 "2018-10-31T14:26:49Z")

</div>

I’ve done it by wrapping the Elm ports in a queue with a locking mechanism. That’s JS stuff I mean. Not on the Elm side.

---

<div class="post-metadata">

**Author:** ![clofresh](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/clofresh/32/1455_2.png) [@clofresh](https://discourse.elm-lang.org/u/clofresh)\
**Post date:** [October 31, 2018, 7:48pm UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/8 "2018-10-31T19:48:40Z")

</div>

This is awesome! Curious, how long does it take to compile in 0.19?

---

<div class="post-metadata">

**Author:** ![vankeisb](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/vankeisb/32/1461_2.png) [@vankeisb](https://discourse.elm-lang.org/u/vankeisb)\
**Post date:** [October 31, 2018, 8:00pm UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/9 "2018-10-31T20:00:35Z")

</div>

We have not yet migrated to 0.19, so I can’t say. I’m curious to see that as well !

---

<div class="post-metadata">

**Author:** ![pdamoc](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/pdamoc/32/36_2.png) [@pdamoc](https://discourse.elm-lang.org/u/pdamoc)\
**Post date:** [November 1, 2018, 6:57am UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/10 "2018-11-01T06:57:45Z")

</div>

> [@vankeisb](#):
>
> Sometimes you’d like to do synchronous calls, but you can’t. We wrote native modules for that.

Can you share what needs do those synchronous calls fill?

---

<div class="post-metadata">

**Author:** ![dillonkearns](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dillonkearns/32/1587_2.png) [@dillonkearns](https://discourse.elm-lang.org/u/dillonkearns)\
**Post date:** [November 1, 2018, 1:12pm UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/11 "2018-11-01T13:12:04Z")

</div>

> [@vankeisb](#):
>
> Ports == lots of boilerplate and “loose” typing : we pass Values because we need to encode/decode ourselves… codegen to the rescue ?

You might find my [elm-typescript-interop](https://github.com/dillonkearns/elm-typescript-interop) library useful. It does exactly this, codegens a TypeScript declaration file based on the ports in your app. I [discussed it in more depth at this year’s Elm Conf](https://youtu.be/memIRXFSNkU).

Great to hear your experience report, thanks for sharing that with the community!

---

<div class="post-metadata">

**Author:** ![vankeisb](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/vankeisb/32/1461_2.png) [@vankeisb](https://discourse.elm-lang.org/u/vankeisb)\
**Post date:** [November 3, 2018, 11:44am UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/12 "2018-11-03T11:44:09Z")

</div>

To be fair, most of our native modules could (should) have been either written in pure Elm, or implemented as ports. We have stuff like input validation (reusing some regexes etc), which we wanted to reuse back in a time when everybody wasn’t comfortable with Elm.

There’s one case that, as far as I know, cannot really be covered by ports though.

We use dojo’s i18n system in order to have localized messages in the app. Our dojo components already heavily rely on that mechanism, so we didn’t want to have several different i18n “libs” and message files in the app. Having everything in our “standard” dojo format is also mandatory for people who translate the message bundles.

So what we do is :  
1/ generate a “strong typed” .elm file from the dojo message keys (we parse and interpret dojo’s .js message files), so that, in Elm code, we can write stuff like “text \<| I18n.messages.my.key arg1 arg2”. That way, the Elm code doesn’t even compile if you try to use invalid message keys (which is pretty cool : with dojo you’ll discover the problem at runtime).  
2/ the generated I18n.elm file has to invoke dojo’s i18n stuff somehow, and this is where it needs to be sync, so that we can just call those funcs from our views.

I don’t know how we are going to do this without native modules yet.

---

<div class="post-metadata">

**Author:** ![szabba](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/szabba/32/562_2.png) [@szabba](https://discourse.elm-lang.org/u/szabba)\
**Post date:** [November 3, 2018, 3:35pm UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/13 "2018-11-03T15:35:18Z")

</div>

Do the translations need to be supplied at runtime? Do they need to change at runtime without a page reload?

---

<div class="post-metadata">

**Author:** ![vankeisb](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/vankeisb/32/1461_2.png) [@vankeisb](https://discourse.elm-lang.org/u/vankeisb)\
**Post date:** [November 3, 2018, 5:36pm UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/14 "2018-11-03T17:36:31Z")

</div>

Yes, dojo loads the appropriate message bundle(s) at runtime, so that you don’t fetch all the translations, but only the one that you need for the user’s locale.  
It is based on the AMD loader : you basically require ‘my/messages’ with a loader plugin (dojo/i18n), and then access the messages on the object :

```
define(["dojo/i18n!my/messages"], function(messages) {
    ...
    var msg = lang.replace(messages.my.key, arg1, arg2);
    ... 
}

```

Our native module just wraps this messages object, and we generate a “façade” over it so that keys are “typed” :

```
I18n.messages.my.key arg1 arg2 

```

instead of

```
I18n.message "my.key" [arg1, arg2]

```

I think reloading in case of locale change would be a acceptable, because that’s not something you do frequently.

---

<div class="post-metadata">

**Author:** ![szabba](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/szabba/32/562_2.png) [@szabba](https://discourse.elm-lang.org/u/szabba)\
**Post date:** [November 3, 2018, 5:52pm UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/15 "2018-11-03T17:52:50Z")

</div>

🤔 That sounds like you could pass the translations to Elm as flags or through a port. It would need to be stored in the model either way. The `I18n` functions would need another argument with the translation strings.

With a flat model (which is often a good idea for other reasons anyway) that could work really nice, I think.

---

<div class="post-metadata">

**Author:** ![vankeisb](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/vankeisb/32/1461_2.png) [@vankeisb](https://discourse.elm-lang.org/u/vankeisb)\
**Post date:** [November 3, 2018, 7:13pm UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/16 "2018-11-03T19:13:54Z")

</div>

Interesting !

I’m not sure that using from the ports module as a definition of the types would be sufficient for us. Most of our ports use Value because we have custom encoders/decoders. We do not use the “default” marshalling/unmarshalling system that ports provide because we use union types and stuff like this in the values we pass around.

I was thinking about some kind of IDL that would allow to describe the types in a language agnostic fashion, and generate the elm ports and the ts.d (or Scala.js façades, or whatever) from this IDL…

---

<div class="post-metadata">

**Author:** ![dillonkearns](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dillonkearns/32/1587_2.png) [@dillonkearns](https://discourse.elm-lang.org/u/dillonkearns)\
**Post date:** [November 6, 2018, 11:13pm UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/17 "2018-11-06T23:13:56Z")

</div>

> [@vankeisb](#):
>
> We do not use the “default” marshalling/unmarshalling system that ports provide because we use union types and stuff like this in the values we pass around.

Yes, I’ve been thinking about ways to support serializing/deserializing Custom Types in `elm-typescript-interop`. I tried to gather some feedback from the community [in this thread](https://discourse.elm-lang.org/t/generating-type-safe-ports-from-custom-types/1841/10), but it’s a pretty challenging problem to find an elegant solution to. I’d love to hear creative ideas if anyone has thoughts on how to make this a nice experience. It’s not challenging technically, but making the process simple and intuitive is quite tricky!

---

<div class="post-metadata">

**Author:** ![ChristophP](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/christophp/32/1528_2.png) [@ChristophP](https://discourse.elm-lang.org/u/ChristophP)\
**Post date:** [November 14, 2018, 12:55pm UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/18 "2018-11-14T12:55:42Z")

</div>

@vankeisb awesome to hear that even IBM is using Elm for more than just POCs 🙂  
About your native code around translations. Maybe [https://package.elm-lang.org/packages/ChristophP/elm-i18next/latest/](https://package.elm-lang.org/packages/ChristophP/elm-i18next/latest/) is for you. It supports also uses runtime translations and supports elm 0.18 (version \<= 2) and 0.19 (version 3) .

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [November 24, 2018, 12:55pm UTC](https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364/19 "2018-11-24T12:55:44Z")

</div>

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
