Backends as you know it are gone. Gone forever. Think end-users and elegant layering

This post belongs to a broader mini-series on how we do Single Page Apps. So I advice to have a quick look there to know context a bit

You sure do remember days of starting new project with coolest, modern MVC framework in your favourite language, and picking your favourite ORM you could die for evangelizing, and hating all other database systems that are different than the one you worship?

Well, you are wrong then. .. So did I.

We must remember, it all ends up with an app that user uses via browser and gives a fuck to all the technology we use underneath.

Users want a working thing (a game, an app, a website, a crm, intranet app, you name it..) that is:

  • responsive (aka Single Page Application)
  • does what they need (aka early prototyping, and having short feedback loop)
  • they can change it (aka change of requirements)
  • error free (aka show me your code)
  • error free (aka maintainable)
  • multiplatform (aka shared codebase)

I coded few years here and there, being Java fanboy, Python, bit of Ruby, all the time doing some shitty Javascripts and always trying to hide SQL complexity behind orms (Hibernate, SQLAlchemy, AR) for mysql, postgresql and bit of mongo and sci-fi prevalence.

But – always trying to write readable backend code.

I end up today writing FRONTENDS, SPAs, javascripts, usecases, roles, with no evil inheritance, no orms, little code reusing, but finally having code that matters, that shows real purpose and is read well, and does what it should.

Some of you may have already read Uncle Bob’s Clean Architecture blog post on separating layers.

You’ll find similarities in GameBoxed styled architecture on how we do it.

In the system core there are usecases.
Usecases are the behaviour and are pure. Plain, old, Javascript objects. No db, no ajax, just plain classes, simple data structures, nothing persisted! (later on that..)

There can be many usecases, implementing some fraction of business domain. They will mostly use rather dumb objects (you could say your model).
When you look there, you should see clearly what is the app purpose and behaviour, flow of user scenarios.

So let’s jump straight to our code, and see for ourselves.

To repeat: pure domain. You can test it in command line. You can run it in the browser environment. You could run it in any backend supporting JS if you’d like.

Give it some input (load data), use it and work with its output. May be as the BLACK BOX for you.

Usecases have three types of methods

  • Input: entry points to accept end-user requests (we name them with words from business domain, but these requests come from naive clicks, or text inputs, or finger swipes, or whatever else a user can do to our app) “playerFinishedTutorial()”
  • Output: empty methods that are results of some important logic happened. You can think of it as events too. “readyToStart(), nextSecondElapsed(), playerGotPoints()”
  • private methods of a usecase

Let’s see one that requests something from a usecase. A simple one this time:

Data of a usecase lives in browser’s memory. It’s a live data structure (a state machine one could say) that changes only because of a user request, or when some time countdown completes. So when it changes, it communicates it … ehmm.. on itself (you’ll see why later)

No domain method knows about view, nor communicates with it directly!.

To connect output of a usecase to external services, view, sounds we are applying a thing called “glue”.

We glue 2 layers together: domain and view. In both directions. It’s thin layer! Knows how to pass parameters. We do it with simple AOP.

This way an internal layer (domain) can engage and pass the “message” to outer layer (a view, a sound subsystem, a social platform, a REST api, whatever)..
And vice versa. If end-user needs to interact with an app, then glue passes message from view (clicks) down to domain via input methods.

See it in action: a glue for web DOM representation of a domain. (we do have different glue for playing sounds, or talking to Facebook social platform)

And to have complete picture of what we call view layer, let’s see view:

How persistence is handled? Might be this way:

Now, these are the basics! Knowing that let’s move on further!

We do start with a browser. We code in the browser. We separate code into clean layers. View knows nothing about domain and domain knows nothing about MANY services that use it.

Glue (many glues) ties together these layers.

Domain tests can be written in command line. Domain is written as the first one. With it being clean we achieve simplicity and less bugs if any. As it is often written in same words a human would describe a business process in more or less “programming English”.

Having it AND NOT WORRYING about persistence, not worrying about backend!, we can provide early, working in the browser prototype of the software. This can be shown to end user and validated and again modified, and… again.

This way of working has been verified and used through several of our apps. We have games too. Games that players play and have fun. And developers have fun too.

What about backend? It’s a browser. So user can do whatever can to hack Javascript and run own code (aka console). And we’d love not to duplicate business logic on backend too :-}
There are at least 2 realities. And any way, backend is just a plugin to our overall architecture. Can be plugged in, or off.

  • we care about hacking via browser
  • we don’t care about hacking

Sometimes it’s just the surroundings of an app business, that we may allow mild hacking. If minor things happen, we just save developers time and $$$ and move on to the next project.
Or maybe it’s a safe intranet environment, where we can trust users? Or we can just trace their actions via logs. If that’s OK that’s great!

Sometimes though, we would be sorry if only frontend would drive backend persistence. And thus for example a HTML5 game player could influence his earned points, and made himself the one in top of hiscores. We’ve seen gamers with 999999999 points, haven’t we?

There are really 2 ways we can take:

  • we duplicate Javascript domain code into our fav backend platform (Ruby, Python, Java.. whatever)
    We know it’s caveats but that might be the only option. Not so bad, if done AFTER frontend is complete. As it’s just a rewrite + maintenance after (keeping code in sync)
  •  we reuse domain JS code in some backend that can run native JS. Node obviously. What else? JVM? Ruby? Tell me please.
    It’s not so easy for non-Node platforms, but can be done. And if the domain logic is heavy, then it just can make sense.

A word of advice. A browser is an ideal platform to do real Model-View-XXX strategy. It’s where your domain code will shine again. Stress free, elegant, and most important .. nothing new really.

You can always follow me on @nthx17. Further working ideas from space will come soon :-)

  • Michał Łomnicki

    I totally agree it is a very clean way of writing code. I try to follow the Gameboxed-way in my apps and it looks very promising so far.
    However I think you oversimplify persistance a bit.

       After(@usecase, ‘readyToStart’, => @serverSide.storePlayerIsReadyToStart())
       After(@memory, ‘readyToStart’, @gui.showStart)

    In that case you show the start screen no matter if data was persisted or not.
    Probably the storePlayerIsReadyToStart method should take 2 arguments – success and error callbacks.

    Any better idea than doing something like this?

        After(@usecase, ‘readyToStart’, => @serverSide.storePlayerIsReadyToStart(@gui.showStart, @gui.showError))

    • Tomasz Nazar

      Well. a) In general I tend to do server side in parallel to view logic.
      b) As an end-user I’m interested in app working, and seeing errors only when something major happened.

      This example is really minor – I doubt seeing tutorial twice or more (in case of error persisting) will cause lot of pain to end user.
      But if that would be something more important .. let’s say “storing points”, I’d extract a separate feature of error-recovery-as-long-as-system-can-in-background. 
      We can schedule all persisting requests to browser local storage first, we can do a queue, and push/pool it to backend. On error frontend could repeat (if makes sense) a request to backend several times until backend really says it can’t respond with HTTP OK. Then as a last resort if all retries failed and user closes browser, then I would show info to user that he looses data.

      Similarly as Gmail does when sending email in background with undo feature set to ON.

      => It goes background <=

      I can start sending/browsing other emails while it sends my previous email. If I close the browser and it's still doing operations, then it will communicate to me.

  • Michał Ostruszka

    Good post. I have one question though: why do you prefer kind of “artificial” empty methods instead of simple events? The only reason I can make up is that you don’t want any “infrastructure” code in you usecase but I’m not sure.

    • Tomasz Nazar

      Well, good question. We did have events before. We had a special “event bus” global object floating around everywhere.
      With empty methods and aop, we can make extra things though. We can adjust when we want applied code to be executed “after, before, or even instead”.

      Besides that, it’s almost the same. Probably personal preference.

  • herval

    No, it’s not gone forever. Remember 5 years ago? RIAs were “the future”, and many, many people invested in client-side tech such as Silverlight or Adobe Flex. Then the wave changed back to server side again, with new, sleek frameworks flourishing everywhere (rails, django, play, even nodejs).

    We’re slowly getting back on the “everything on the client side” phase now. Javascript is not “the silver bullet”. Becoming a fanboy AGAIN (with a different tech) is not the way to go. The “javascript everywhere” movement itself is a re-enacting of the “Java everywhere” meme that lasted for almost a decade and produced aberrations such as GWT and Applets (incidently growi a generation of “web” devs that fear javascript).

    Plus, you can have responsive, easy to change and error free apps regardless of technology…

    • Tomasz Nazar

      You’ve probably already read, but I advice to see today’s

      It’s how we tend to treat important backend as less important in the first phases of our projects.
      It’s the way works for us very well. Has few cool benefits.

      I’d say to myself “fuck last 10 years” – just use whatever suits me nowadays. Works for me. I will still try to tell you how it works exactly in new posts few days from now.
      We take problems from today and software and knowledge that exists today and try to use max out of it in this particular way :-)

      • herval

        “Fuck the past” is the best way to repeat all the same mistakes, again and again. A specially conspicuous habit of the “JS-everywhere” and “MongoDB is God” groups, these days (this realm used to be dominated by the “Java certified fanboys”, but those have all migrated into other communities, and now preach “the new right”)

        “All this will happen again, and this have happened before”…

  • Pingback: qwxgvnmkfbrvecganfhv

  • Pingback: csevdhrbmkgnkjbhvdbjn

  • Pingback: bgsvcvbhjfgmnbdvgbnhg

  • Pingback: csngrdngthnfgdsfgnsfsd

  • Pingback: gxcrcfgrtgsgabdjnhacfg

  • Pingback: dr oz belly fat supplements

  • Pingback: buy garcinia cambogia extract pure

  • Pingback: getting rid of bed bugs