We’ve talked now about cost & benefit for thin-client, i.e. browser solutions. What are the cost & benefit of fat-client, i.e. app solutions?
There is one primary cost for a fat client, as opposed to a thin, and it’s obvious:
It doesn’t write-once-run-anywhere.
Now a couple of things.
- We’ve already pointed out that a thin client doesn’t do that, either. But — play fair — thin clients usually run at least "okay" in more places than fat ones do.
- That doesn’t mean that a fat client only runs in one place. A fat javafx client, for instance, can readily run on any PC, Mac, or Linux, and on most (but not all) pads. The place it mostly doesn’t run is on your phone. (That may be changing, but promises promises, we’ll see.)
- I am most familiar by far with the java family. There are other approaches that create something close to being able to run on any ordinary pc, a pad, or a phone. They’re "close". Until there’s really a standard way to write phone apps, it still means some heartache.
There is a noted — though I believe overestimated — secondary cost to a fat client: the victim, I mean customer, the customer, has to install it one time.
Why do I say it’s overrated? Well, geeks tend to think of "install an app" as something like installing, say, Microsoft Office. It takes forever. It forces reboots. It’s liable to break other apps that were working fine. If the install chokes you’re looking at hours of stress.
But instead, think about your phone. You install apps on your phone routinely. They take a couple of minutes. They (mostly) don’t break. They (mostly) don’t choke. They (mostly) just work. Fat clients are fat, but they’re aren’t Microsoft Office. In fact, because phones are so ubiquitous, and apps are commonplace there, users have become quite adjusted to snagging an app. It’s just not that hard or risky nowadays.
So there’s a couple of costs, and they’re real. But what do we have in the benefits department? Here’s where fat clients shine. To list them, let me pause and describe an app.
(I don’t want to overstate the completeness of this app. I can’t show it. I barely have partial product. But most of what I’m talking about I’ve either coded into the current app, or have coded in the past and am re-coding in the new one. You’ll have to trust me a little.)
The app is pure client. It does only the tiniest amount of work, mostly formatting json for outgoing and rendering json for incoming. It does do a little pre-processing, and there’s auth stuff, but purposefully very little. The real work is done on the service.
The app and the service are both written in Kotlin, meaning I have the whole javascape for libraries, snippets, and stack overflow. It uses TornadoFx to front the JavaFx ecology. (Tornado’s quite nice, I recommend it.) This app auto-updates. In fact, it auto-updates on each run direct from the head of the repo. It uses a library and a nexus repo to do this.
It shows a fairly standard UI. Standard in the sense of modern upscale, mind you, not in the sense of "looks like an 80’s web app".
Here’s the first benefit, a huge one: there is one formal language, the same formal language as the service is written in. There are tiny bits of CSS, but I’m not wild about CSS, and I only use it when I can’t use direct library calls. There are some pseudo-languages, TornadoFx on the client side, and Spring and SQL (or Hibernate or JPA) on the service side.
Compared to the browser stack, life here is ridiculously simple. It’s kotlin. Change the location of that button? Kotlin. Add a new service endpoint? Kotlin. Change the JSON structures? Kotlin. Write a microtest? Kotlin. Write an integration test? Kotlin.
(Plus the pseudo’s.)
One formal language has two follow-on benefits that are also dramatically different from the thin-client approach.
First, there’s just one main tool, JetBrains’ IDEA. One tool. One set of hotkeys. One standard window structure. A tool that knows every corner of the source code.
Second, it’s actually only one app (during development). That is, the client and the service are the same program running in the same process on the same box. Orrrrrrrrr… not. That is, it can be just the client. It can be just the service. It can be both.
As a geek, this means a lot. I can set any breakpoint anywhere at any time. I can use println debugging. I can write tests that cross the gap, or tests that only exercise the client, or tests that only exercise the service.
(I’ve started twitching code again, and I’m in the middle of a short series. When I finish that, I’ll show you how to write the code that does that.)
There’s another huge benefit, in stark contrast with the normal browser stack: my team has complete and perfect control over the update stream. We decide what to change when, not a browser company. In the app I’m speaking of, we update on every run, but of course, that’s a choice we made, based on our confidence that HEAD is always viable. We could just as easily gate the updating in many different ways.
And one more benefit: as developers we can use any kind of layout technique we want. We can directly measure the screen, we can account for orientation, we can change layouts faster than you can spell "class=’…’". And because it’s all in code, we can eliminate virtually every trace of duplication and noise. We can enforce any visual standard we like. We can customize literally any aspect of the UI.
And security: no cross-site scripting issues. Anything safe in TLS is safe in our app. There are no backdoors, because there’s no browser tools. We can encrypt 100% of our traffic, and we can easily guarantee the quality of that encryption.
So. Costs and benefits, thin and fat. Let’s summarize.
- The point of the valuation is not that you come to believe fat is always better than thin. It is that you come to believe that neither — neither — is a default goto solution. Each client case is different in how it provides value. You will have to decide, consciously.
- Thin runs more places than fat, nearly always. But it costs a lot more, too, nearly always. Is it worth it? Maybe. Maybe not.
- Fat enables change far more readily than thin, for reasons of sheer simplicity. One or two tools. One language and a couple of pseudo-languages. It’s possible to even do it in one program/process.
- Relentless imbalance, focusing always and ever on the Made, can easily prevent your product from ever reaching the market. When we consider what to do, we need to balance our attention to the Made with roughly equal attention for the Making and again for the Makers.
When I can deliver the value in a fat client, I always do. That’s how much the cost-benefit valuation I just gave means to me. In fact, if it takes me two fat clients to cover my market, I’d still rather write two of them than one browser client.
The hardline question to ask every time: what portion of my market is browser-only?
That’s really the big first question. The answer to that determines everything else.
So. Fat vs thin. People ask me why I prefer fat when the value proposition can work with fat. And now I can hand them a written answer.
That’s it for now. Maybe soon I’ll write more about building for service-on-service environments, a topic that’s dear to me.
Meanwhile, though, I hope you are gently perturbed on this fine Thursday morning, and something makes you see things in a different & pleasing way.