Monthly Archives: May 2018

Minimalistic Services and Applications

Question: There are plenty of documentation, patterns, architectures and practices for scaling up your cloud Services and Applications solution. But how do I scale it down?

In 2015 I set up a minimalistic architecture for delivering Services and Web Applications. It was based on 15 years of experience (not only positive) on constructing and operating applications, services, servers and integrations. Now in 2018 I can say that my architecture is doing very fine. I have continously been delivering business value for 3 years. I will share some principles and technical details.

Limitations and reservations
Not all solutions are good for everyone. Neither is mine. If you know that you want worldwide internet scalability my architecture is not for you. But often you are building applications that are internal for your organisation. Or you have a local/regional physical business that you need to support with services and applications. Then you know that there is a practical upper limit of users that is not very high.

While modern cloud services are supposed to scale more or less unlimited this does not come for free. It comes with complexity and drawbacks that you may not want to pay for, since you are anyway not aiming for those gigantic volumes of users and data.

The architecture I am presenting is designed both to perform and to scale. But within limits. Know your limits.

Microservices
Microservices is about many things. I have made a practical interpretation.

My… delivery platform… consists of microservices that communicate with each other. They should have limited responsibilities and they should not grow too big. Each service should store its own data, really. Two different services should share data via their (public) APIs, never by using a shared storage.

I ended up with a separate Authentication Service (knowing about users and credentials) and Roles Service (knowing about roles/priviliges granted to a user). In hindsight perhaps this could, or should, have been just one service. On the other hand, if I want to store something like personal Settings/Preferences for each user, perhaps it is good that it does not go to a common single User service that grows more complex than necessary.

As you may know, there is another Microservice principle about each service being able to run in multiple instances and that (via Event Sourcing and CQRS) state is not immediately consistent, but eventually consistent. I normally outright break this principle saying that a single service has a single instance holding the single truth. I feel ok doing this since I know that each service is not too big, and can be optimized/rewritten if needed. I also feel ok doing this because I know I save a lot of complexity and my approach opens up for some nice optimizations (see below).

It is all about HTTP APIs
My microservices talk to each other over HTTP in the simplest possible way. The important thing is that your web applications, native (mobile) applications, external partners and IoT-devices use the same APIs.

I want it to be trivial to connect to a service using wget/curl, an Arduino, or any left behind environments my clients may be using. I also want any server platform to be capable of exposing APIs in a conforming way.

What I basically allow is:

http://host:port/ServiceName/Target/Action?token={token}&...your own parameters

Your service needs to have a name and it is in the URL. Target is something like Order or Customer. Action is something like Update or Cancel. token is something you need to obtain from the Authentication Service before making any calls. You can have extra parameters, but for more data it is preferable to POST a JSON object.

I dont want any extra headers (for authentication, cookies or whatever) but I respect Content-Type and it should be correct. Absolutely no non-standard or proprietary headers.

I only use GET and POST. It just doesn’t get clear and obvious enough if you try to be smart with PUT and DELETE.

For things like encryption (HTTPS) and compression (gz) I rely on nginx.

Reference Implementation
The above principles constitute the Architecture of a number of services together making up a virtual application and service platform. As you can see you can build this with almost any technology stack that you want. That is the entire point!

  • You may want to make API calls from known and unknown devices and systems in the future
  • You may want some legacy system to be part of this virtual delivery platform
  • You may want to build some specific service with some very specific technology (like a .NET service talking to your Active Directory)
  • You may find a better technology choice in the future and migrate some of your services from current technology

But for most purposes you can build most services and applications using a few, simple, free and powerful tools. More important than the tools themselves are established standards (HTTP, HTML, JavaScript and CSS) and principles about simplicity and minimalism.

JSON and JavaScript
After working for years with integrations, web services (SOAP), XML, SQL databases and .NET I can say that the following type of technology stack i common:

  1. Web application is written in JavaScript, works with JSON
  2. Web application communicates with server using XML
  3. Server processes data using .NET/C#
  4. Data is persisted using SQL queries and a relational database

This means that a single business object (such as an Order) has data representations in SQL, C#, XML and JSON. This means that you have several mappings or transitions in both ways. You can also not reuse business logic written in SQL, C# or JavaScript in another layer of your application.

With Node.js you have the opportunity to do:

  1. Web application is written in JavaScript, works with JSON
  2. Web application communiates with server using JSON
  3. Server processes data using JavaScript and JSON
  4. Data is persisted in JSON format (either in files or a database like MongoDB)

This is simply superior. A lot of problems just disappear. You can argue about Java vs C#, HTTP1 vs HTTP2, Angular vs React and things like that. But you just cant argue about this (the fundamental advantage a pure JS stack gives you – not because JavaScript is a superior language but because it is the defacto language of the web).

So my reference platform is based on Node.js and I store my data in JSON.

Binary formats
Binary formats have their advantages. It is about power and efficiency. But rarely the differences are significant. Base64-encoding is 33% more expensive than the original binary. Compiled languages are somewhat faster and use less memory. But humans can’t read binary. The compilation (or transpilation) into binary (or machine generated code) is not only an extra step requiring extra tools. It also creates a longer distance between the programmer and source code on one hand and the execution and its error messages on the other hand. Source maps are a remedy to a problem that can be avoided altogether.

I was once responsible for a .NET solution (with Reporting Services) that was so hard to change and deploy that we eventually refused to even try. I realised that if the system had been coded in the worst imaginable PHP I could have made a copy of the source (in production), modified the system (in production) and restored the system if my changes were not good.

Similar problems can appear with databases. Yes, you can make a backup and restore a database. But how confident do you feel that you can just restore the database and the system will be happy? What is IN the database backup/restore, and what is configuration outside that database that might not be trivial or obvious to restore (access rights, collation settings, indices and stored procedures, id-counters, logging settings and so no).

So my reference platform minimises the use of binary formats, build steps and databases. I code plain JavaScript and i prefarably store data in regular files. Obvously I use native file formats for things like images and fonts.

Storage
Some appliations have more live data than others. I have rarely come across very large amounts of transaction or record data. I have very often come across applications with little data (less than 100Mb) and a truly complex relational database. I have also seen relational databases with not too much data (as in 1GB) with severe performance problems.

So, before architecting your solution for 10-100GB+ data, ask yourself if it can happen. And perhaps, if it eventually happens it is better to deal with it then?

Before constucting a relational datamodel with SQL ask yourself if it is really worth it.

Since we are using a micrsoservice strategy and since services share data via their APIs two things happen:

  1. Most services might get away with very little (or no) data at all (while some have much data)
  2. A service that later turns out to need to deal with more data than it was first built for can be refactored/rebuilt without affecting the other services

So I suggest, if in doubt, start small. What I do (somewhat simplified) is:

  1. Start up Node.js service
  2. Load data from local files into RAM
  3. All RO-access is RAM only
  4. When data is updated, I write back to file within 10s (typically all of it every time, but I keep different kinds of data in different files).
  5. Flush data before shutting down

This has an advantage which is not obvious. JavaScript is single-threaded (but Node.js has more threads) so a single request is guaranteed to finish completely before the next request starts (unless you make some async callback for waiting or I/O). This means that you have no transaction issues to deal with – for free – which significantly simplifies a lot of your request handling code and error handling.

Another advantage is that RAM is extremely fast. It will often be faster and cheaper to “just access all the data in RAM” than to fetch a subset of the data from a database and process it.

This may sound like “reinventing the wheel”. But the truth is that the above 1-5 are very few lines of quite simple code. You can use functions like map(), reduce() and filter() directly on your data without fetching it (async) first. That will save you lines of code.

Again, this may not work for all your services for all future, but it is surprisingly easy and efficient.

Code, Storage, Configuration and installation
When I check out my (single) git repostory I get something like:

packages/                         -- all my source code and dependencies
tools/                            -- scripts to control my platform,
                                     and a few other things

I then copy the environment template file and run install (to make node_modules from packages):

$ cp tools/env-template.json dev.json
$ ./tools/install.sh

This config file can be edited to replace “localhost” with something better and decide what services should run on this machine (here, in this library) and where other services run if I use different machines. Now I start the system, and now I have:

$ node tools/run dev.json ALL     -- use dev.json, start ALL services

dev.data/                         -- all data/state
dev.json                          -- all environment configuration
node_modules/
packages/                         -- all code
tools/

I can now browse that services on localhost:8080, but to login I need to create an Admin user using a script in tools (that just calls an API function) before logging in.

Notice how easy it is to start a new environment. There are no dependencies outside packages. You may create a dev-2.json which will then live in dev-2.data side by side with dev. To backup your state you can simply backup dev.data and move it to any other machine.

Lets have a look at dev.data (the files for one service):

Authentication.localstorage/     -- all data for one service
Authentication.log/              -- a log file for one service (kept short)

In packages you find:

common/                          -- JavaScript packages that can be used
                                    on Node as well as web
node/                            -- Node-only-packages
services/                        -- Node-packages containing services
web/                             -- JavaScript packages that can be used
                                    on the web only

You shall include tests on different levels (unit, integration) in a way that suits you. The above is somewhat simplified, but on the other hand in hindsight I would have preferred some things to be simpler than I actually implemented them.

Notice that there are no build scripts and no packaging required. All node code is executed in place and web applications load and execute files directly from packages/.

Serving files, input validation, proxy and nginx
Node.js is very capable of serving files (and APIs) just as it is. I have written a custom Node.js package that services use to handle HTTP requests. It does:

  • Validation of URL (that URLs conform to my standards)
  • Authentication/authorization
  • Is it a file or an API call
  • Files: serve index.js from common/ and web/, and www/ with all contents from all packages
  • APIs: validate target, action (so it exists), validate all URL-parameters (dates, numbers, mandatory input, and so on)

This may seem odd but there are a few good reasons for doing exactly this.

  1. Service APIs and policies are metadata-driven
  2. Consistent good logging and error messages
  3. Consistent authorization and 401 for everything questionable (both for files and APIs)
  4. The same service serves both API and www-files which eliminates all need to deal with cross-site issues (which is something of the least value-adding activity imaginable)
  5. Consistent input validation (if there is anything I don’t trust people get right every time they write a new service this is it)

You can probably do this on top of Express, or with Express, if you prefer not to use Node.js standard functionality.

At this point, each service listens at localhost:12345 (different ports) so you need a proxy (nginx) that listens to 80 and forwards to each service (remember the service name is always in the URL).

I prefer each service to handle all its API calls. Quite often it just forwards them to another service to do the actual job (lets say a user action of the Order service should create an entry in the Log service: the Order web UI calls Order/log/logline, which in turn calls the Log service). This can be very easily achieved: after authentication/authorization you just send the request through (standard Node.js does this easily).

Dependencies
The web has more npm packages than anyone can possibly want. Use them when you need (if you want, read Generic vs Specific Code, Lodash and Underscore Sucks, …).

My biggest fear (really) is to one day check out the source code on a new machine and not being able to install dependencies, build it, test it, run it and deploy it. So I think you should get rid of dependecies and build, and rather focus on testing, running and deployment.

I think, when you include a dependency, place it in packages/ and push it to your repository. Then you are in control of updating the dependency when it suits you. New dev/test/prod machines will get your proven and tested versions from packages/, regardless what the author did to the package.

This approach has both advantages and disadvantages. It is more predictable than the alternatives and I like that more than anything else.

Error handling
I take error handling seriously. Things can get strange in JavaScript. You should take the differences between numbers and strings, objects and arrays seriously (thats why you should not use Lodash/Underscore). There are no enums to safely use with switch-statements. I often add throw new Error(…) to code paths that should not happen or when data is not what I expect.

On the (Node.js) server I don’t have a big try-catch around everything to make sure the server does not crash. I also don’t restart services automatically when they fail. I write out a stack-trace to and let the server exit. This way I always work with a consistent, correct state. Critical errors need to be fixed, not ignored. This is the Toyota way – everyone has a red button to stop production if they see anything fishy. In effect my production system is among the most stable systems I have ever operated.

Validation, models and objects
Data validation is important. Mostly, the server needs to validate all data sent to it. But a good UX requires continous validation of input as well.

I put effort into defining models (basically a class in an OO language). But since my data objects are regularly sent over the network of fetched from disk I don’t want to rely on prototypes and member functions. I call each object type a model, and early on I write a quite ambitious validation-function for each model.

Sharing code between Node.js, web (and AngularJS)
I want my code (when relevant) be be usable on both Node.js and the Web. The Web used to mean AngularJS but I have started not using it.

This is what I do:

 /*
  * myPackage : does something
  *
  * depends on myUtil.
  */
(function() {
  'use strict';

  function myFactory(myUtil) {

    function doSomething(str) {
      ...
    }

    return {
      doSomething : doSomething
    };
  }

  if ('undefined' !== typeof angular) { // angular
    angular.module('mainApplication').factory('myPackage',
                  ['myUtil',
          function( myUtil ) {
      return myFactory(myUtil);
    }]);
  } else if ( 'undefined' !== typeof MYORG ) { // general web
    MYORG.myPackage = myFactory(MYORG.util);
  } else if ( 'undefined' === typeof window ) { // nodejs (probably)
    module.exports = myFactory( require('common/util') );
  } else {
    throw new Error('Neither angular, node or general web');
  }
})();

This way exactly the same source code can be used both on the web and in Node.js. It requires no build step. The “general web” approach relies on a global object (call it what you want) and you may prefer to do something else. You just need to make sure you can serve common/util/index.js and common/mypackage/index.js to the web.

Scaling and cloud technology
For a simple development system, perhaps for a test system or even for a production system, everything can live in a single folder. If you need more power or separation you can put each service in a Docker container. You can also run different (groups of) services as different users on different machines.

So, the minimalistic architecture easily scales to one service per machine. In practice you can run a heavy service on a single machine with 16GB RAM (or more) which will allow for quite much RW-data. 16GB or more RAM is quite cheap compared to everything else.

Scaling and more data storage
There are many other possible strategies for a service that needs more storage than easily fits in RAM (or can be justified in RAM).

Some services (like a log) is almost exclusively in Write mode. You can keep just the last day (or hour) in RAM and just add new files for every day. It is still quite easy and fast to query several days or logs when needed.

Some services (like a customer statistics portal) has mostly RO-data that is not regularly accessed, and that lives in “islands”. Then you can have (load from other systems) a JSON-file for each customer. When the customer logs in you load that file to memory and later you can just recover that memory. Such a service can also be divided into several services: 1 main RW, 1 RO (A-L), 1 RO (M-Z).

Some services will do expensive processing or perhaps expensive communication/integration with other systems. Such processing or integration can be outsourced to a dedicated service, freeing up resources in the main service. If you for example generate a PDF, make sure you do it in a process outside Node.js.

In the same way a service can offload storage to another service (which could possibly be a MongoDB).

Web files (html, css, images, js) can be cached by nginx (if you accept to serve them without authentication) and served virtually for free even if your service has full control.

Things like logging can also be outsourced to a dedicated and enterprise class logging software. Nevertheless, it is good to have a simple reference Node.js logging service that can be used for development purposes locally.

Finally, GDPR indicates that you should throw away data. You can also move data from a live system to a BI-system or some Big Data tool. Perhaps your architecture does not need to support data growth for 10+ years – perhaps it is better it does not.

Scaling – conclusion
These scaling strategies may not sound too convincing. But the truth is that building your entire system in a single very powerful monolith is probably going to be less scalable. And building everything super scalable from the beginning is not easy or cheap (but if thats what you really need to do, go ahead).

Integration testing
Notice how integration testing can be achieved locally, automated, with virtually no side effects:

  1. Generate a integration-env.json
  2. Start up services (as usual)
  3. Run tests to inject data into the services (throw standard APIs)
  4. Run tests to read data, query data
  5. Shut down services
  6. Remove integration-env.json and integration-env.data/

Source control and repositories
For now, I have all code in a single git repository. It would be easy to use multiple repositories if that simplifies things (when developing multiple independent services at the same time). Linux is in a single git repository so I think my services and applications can be too.

Tooling
All developers prefer different tools and I think this should be respected. I also think coding style does not need to be completely consistent across services (although single files should be kept consistent).

But just as developers should be allowed their own tools, the artifacts of those tools should not make the repository dirty. And the next developer should not need to use the same tools as the previous to be able to keep working on the code.

Web frameworks
If I mastered direct DOM-manipulation I would probably suggest that you should too (and not use any web frameworks). However I have been productive using AngularJS (v1) for years. Since AngularJS is inevitably getting old I have started using Vue.js instead (which I think is actually a better choice than Angular, however check my post about loading vue templates).

React is also a fine framework but it requires a build process. For my minimalistic approach that is a very high and unnessecary addition of complexity. I don’t see any indications that React is fundamentally more productive or competent than Vue.js so I think you are fine with Vue.js (or jquery or Vanilla.js if you prefer).

Performance
I have, to be honest, not had the opportunity to add very many simultaneous users to my system. On the other hand I have used it for rather mission critical services for 3 years with very few issues. So this architecture has served me well – it may or may not serve you well.

My production environment consists of a single VPS with 1 core, 2GB RAM and 20GB storage. Performance is excellent and system load minimal.

Missing Details
Obviously there are a lot of details left out in this post. You dont have to do things exactly the way I did it. I just want to outline an architecture based on minimalistic principles. The details of users, authentication, logging and naming conventions are of course up to you to decide.

Feel free to ask though! I am open to discuss.

Conclusion and final words
I wrote this post quickly and I will probably add more content in the future (and correct/clarify things that could be improved).

 

Review and Strategy: Railway Empire

I have much enjoyed playing Railroad Tycoon II and Railroad Tycoon 3. In a way I prefer the quite refined 2D graphics of RTII to the quite crude 3D-graphics of RT3 but RT3 has an economic model that is more interesting (although far from perfect). Over the years I have waited for Railroad Tycoon 4 and instead I have found games like:

  • Cities in motion
  • Transport Fever
  • Sid Meiers Railroads

They all have their charm and qualities but none of them aspire to be the successor of Railroad Tycoon.

Railway Empire
Then came Railway Empire. I have played it during closed beta and as I write it is still in beta. Railway Empire is a candidate to be the defacto successor of Railroad Tycoon so I will write about different aspects of it.

Graphics
The graphics is nice. It is cartoonish rather than realistic – Railroad Tycoon (esp II) had a more serious look – but its ok with me. The ride-along-mode is quite nice.

Controls
I understand Railway Empire is designed not only for computers but also for gaming consoles. For this reason things are large and quite simplified. You don’t get large tables of facts and statistics and it is more about clicking, sometimes a click or two more than what you want. I think it works well.

Time and speed
This kind of game needs to deal with time. On one hand a train on a line could do several roundtrips on a single day, based on a realistic time table. On the other hand the game should progress day by day or month by month while the trains beautifully cross the landscape. I think Railway Empire gets this quite right. The trains accelerate quite fast and it does not take too many days for them to reach their destination. If I remember correctly, in Transport Fever it takes annoyingly long time to arrive. I have not started up RTII/RT3 to compare, but I think in Railway Empire trains typically return in weeks rather than months (as in RTII/RT3).

A much debated thing is the tactical pause. As it is now the game has three modes:

  • Trainiac: no pause (with a few exceptions): +20% score
  • Normal: game paused when building
  • Manual: can pause whenever you want: -20% score

I personally prefer the Manual mode. I start up a new scenario, listen to the introduction, read the tasks and investigate the map before I start building anything. I don’t want this to take 6 months when the first tasks are to be accomplished in 2 years. Of course I can study the map, take notes, make a game plan and then restart the game but to me that just adds the feeling of cheating. I play Railway empire to relax, not to be stressed.

Nevertheless I can see that the absense of pause makes the game more challenging. Perhaps when I replay the same scenario in the future I can try one of the faster modes.

So I think the three modes are fine.

Rail network mode
There is a simplified mode where several trains can run on a single track. I am not interested in that and I have used the realistic mode that requires signals, where you can get deadlocks and trains can block each other.

Building
Laying tracks is enormously improved since RT3. Without going into detail you can place several segments and see the cost and the inclines. Then you can adjust the curves and height, creating new cuttings, viaducts and tunnels and get a new price in real time. If you are happy you can click $ and you are done. No need to build, delete and start over (or even make tactical saves as in RT3).

Each station can have up to 4 through tracks and each town can have 2 stations. Then there can be (any number of) warehouses also with 4 tracks. So a large city with one warehouse may have 24 outgoing tracks. This works quite well. You can build viaducts and tunnels and the game is quite forgiving. The station itself is just the platforms and you need to extend it far out in the surrounding landscape with parallell tracks for incoming and outgoing trains to avoid queues and deadlocks.

When you have many parallell tracks the switches and curves take more space than would be optimal. There are no crossings. It wouldn’t surprise me if these things get improved before the final version.

In conclusion you can do things you only dreamt of in RT3.

Routing and signalling
One of the most significant changes from RTII/RT3 is the signalling system (not very different from Transport Fever). The important thing to understand is that every train has one exact route that it will not divert from ever (unless you change it), meaning:

  • There is no such thing as available platform (train will wait for its assigned platform to be free)
  • There are no train priorities (in most cases it would have no relevance)
  • The train will take the shortest route (which may not be what you want)

The signalling system is not trivial. I would not be able to explain how it would work in every situation but I  have come up with ways to use it that works for me. The trains pass a signal if the section (until next signal) is free unless it is entering a single track that already have another train coming in the opposite direction. But it is possible to produce deadlocks.

Generally more trains mean more waiting. If you get to the point where you have deadlocks you probably have far too many trains. A lot of the time you increase capacity by making sure the trains you have already deployed easily can get to their destinations rather than deploying more trains on already busy tracks.

In conclusion the signalling system works beatifully but you need to practice a bit before you master it. When I have read other guides it seems other players use the signalling systems in ways I dont.

Town Growth
Each town has demands. Small towns demand small quantities of basic goods (such as wheat). Larger towns also demand more delicate goods (such as vegetables) or manufactured goods (such as furniture).

This means that when you supply a small town with everything it needs it will quickly grow. But then it will start demanding things you are not transporting there and it will stop growing.

Industries transform goods (like wheat) into other goods (like beer). Industries are located in towns and adds to the towns demand. What they produce will be consumed locally (if demanded) and you can also transport the surplus to other towns (where demanded).

Express Goods
Passengers and Mail (express goods) are very easy to deal with. They have a final destination and they will find their way through your network changing trains in intermediate stations. What I lack from RT3 is the map that shows where most passengers are waiting and where they are going (to identify and mitigate bottlenecks).

Freight Goods
Freight is the key to growth and growth is a more important part of Railway Empire than it was to RTII/RT3. I found the freight mechanism confusing at first and it resembles both RTII and RT3 but it is also different.

Local resources (like a wheat farm) can ship limited amount of goods (like wheat) by road to closely located towns. Apart from that there is no goods moving without trains and no and market prices as in RT3.

  • Goods (like beer) produced in one town will be stored/consumed where produced but never transported elsewhere (except by train).
  • Towns that don’t manufacture a type of goods will store it for local consumption only. You can only unload what is demanded. And you cannot load what is unloaded.

Imagine a line with three stations:

  1. A wheat farm
  2. A town with a brewery (demanding wheat)
  3. A town (with demand of wheat)

If you make a simple train go 1-2-3-2(-1) most likely no wheat will ever make it to town 3. Not until you have completely filled up the storage capacity of wheat in town 2 any wheat will make it to town 3.

There are several ways to deal with this like warehouses and manual freight mode (where you configure a train to load/unload exactly what you want). However the best solution is often to simply run a dedicated train directly from 1 to 3 (and combine with other duties if possible/needed).

Congestion
Eventually you will end up with congestion: several trains waiting in line to access the same platform. At this point, adding more trains will do more harm than good.

The obvious solution is to add more platforms and send the trains to different platforms (largers stations also serve trains faster).

But you also need to consider how efficiently you use your platforms. In a busy station the following scenarios are listed from worst to best:

  1. A train arriving, delivering nothing, getting serviced, loading nothing
  2. A train delivering and loading a few wagons
  3. A train passing through
  4. A train unloading all wagons, leaving empty
  5. A train unloading all wagons and loading a full train

This is why manual freight mode is subotimal: arriving with 8 wagons, delivering two loads, loading two wagons and leaving is wasteful utilization of platform capacity. For the same reason, long express (or mixed) goods lines calling at every station is not very optimal if most passangers or goods just go through.

Mostly the cause of congestion and your bottlenecks are your stations not your lines.

Warehousees
A warehouse has 4 tracks and can store goods but it does not belong to a town. In theory if you set things up in a good way you can have full freight trains going from a warehouse into a town with what the town demands and then return fully loaded with manufactured goods to the warehouse where the train gets serviced (maximizing platform utilization in the town itself). You can think of the warehouse as 4 extra tracks that occupy just on track in the town-station itself. In practice this is not very easy.

I have tried to set up warehouses that I fill with basic goods (wheat, corn, lumber, vegetables, fruits, milk). The problem is that wheat is demanded first. So trains will leave the warehouse for large cities that demand all the goods stored fully loaded with wheat only (until the town has reached maximum wheat stocks). This will leave the large city somewhat unsatisfied. Worse, your warehouse will perhaps run out of wheat and your smaller towns will get nothing (because they dont even demand vegetables, fruits and milk which the warehouse is full of).

My conclusion is that as long as you can supply a town with full train loads of anything it is better to go directly from the source(s) to the town. Often you can make a line like:

  1. A-town
  2. Corn farm
  3. Wheat farm
  4. B-town

If you run a train 1-2-3-4-3-2(-1) you get decent utilization. However, you may want to leave A-town and B-town empty, and perhaps you want to load only 4 wagons in the first farms both ways (otherwise B-town will get mostly corn). Even though the above route is nice it could make more sense to do 2-1-2-4-3-1-3-4.

Buying the competition
In RT you were a major investor in your own company. You could pay out dividend and you also received a salary. This money you could invest in your own company or in the competition. Eventually you (as investor) could buy out the competition. However your company could not buy stocks.

This is different in Railway Empire. You – your character – control your company but you can not buy stocks (or receive dividends). Your company can buy stocks in the competition (and they in yours). You can not buy stocks in your own company (it simply would not make any sense to do so).

You may take over (merge with) your competitors by buying 100% of their stocks. And they can take over your company the same way.

I would have wanted to be able to take over a company and let it operate as before, just not expanding. And perhaps being able to transfer industries to my own company. However, what happens when you take over a competitor is that all their trains are sold, tracks and stations are left empty. The good thing is that it makes it reasonable straight forward to set up your own lines and name them the way you want. The bad thing is that it is a lot of work. You have the option of simply liquidating everything receiving cash instead.

Locomotives
Railway Empire has quite many diffent locomotives to choose from and they become available as you research them.

Growing Stations
Stations usually start out small and grow with more lines and trains. This is what I typically do.

1. A single track allowing for a single train to one other station in the east.

2. Double track to the east connected to a single platform. Notice how I already prepared the double track on the south side to continue into the station should it grow. This will allow for future through traffic. If on the other hand I know there will be no through traffic I would place the double track north instead, allowing for more room for eastbound tracks connected to new south platforms.

3. Now I have double track also to the west. No through traffic possible.

4. Now through traffic is possible, as well as trains terminating in Salina from both east and west.

5. Finally, if there is much through traffic and also traffic from the east terminating in Salina I use track #1 (westbound) and #2 (eastbound) for through traffic, and #4 for terminating traffic. Notice that the longer the yard is the less risk for congestion. If you in my example have 3 trains queueing to get to #3 there is a risk that they will block a through train, even though #1 is free.

Intersections
Often two lines need to merge into one line and you can do this in different ways depending on ambition and expected traffic.

1. If you have a double track with a single track going to a station (typically a farm/resource) this works fine. However if multiple trains go to the farm one will wait in the mainline (blocking it) if the farm is busy.

2. The standard way to deal with two double tracks merging is seen below. Note that if the track to the north is the busiest this will cause waitings.

3. For practical this is often good enough (and very simple).

4. The below is an alternative when it comes to splitting the line from the east into two lines with equal priority. The extra complexity offers no advantage to #2 above.

5. This way two trains can meet either E/W or E/N with no train stopping.

6. If you are really serious about avoiding blocking/waiting you can invest in a viaduct. However it costs more and you may lose time because the track is longer and with a significant incline.

In all the above pictures only one-way signals are displayed. You need more signals to allow trains to run closely after each other. As you notice as soon as I have double track I use right hand one-way traffic.

Single Track
Although the price of double track is less than twice a single track often it makes sense to start with a single track. You then need sections were trains can pass (unless you have a single train). This is how I do it, to very easily be able to upgrade to double track later. Notice that those are the only two signals I have. I have seen other screenshots with more signals but I have experienced deadlocks.

If your single track line joins a double track main line, the passing section should be as close as possible to the main line to minimize waiting. The single track is to the north in the picture below.

Single Tracks and Stations
If you have two stations with a line between them the passing section needs to be between them. It makes no sense to have double platform stations.

If you have three stations with a line the middle station can serve as passing section as well.

However, in practice you would probably make the track longer on one side to place a supply tower.

It is generally a bad idea to have through traffic (both ways) on a single platform, especially if some trains also terminate. If you have limited traffic you can have terminating traffic from both ends. And for a rural station with limited traffic you can save money by having passing sections on both sides of a single platform. You can always start cheap and expand later:

Summary
There is so much more to discover and talk about when it comes to Railway Empire! It may not be perfect, but it is certainly much better than RTII and RT3. I think this game will give me many hours of entertainment for the coming years.

X-Wing Second Edition: First thoughts

Fantasy Flight games have announced X-Wing Second Edition. It surprised me a bit but I am quite optimistic. As a somewhat serious casual player I think the game was in need of an overhaul. I see a number of areas of possible improvement. I mostly fly rebels/resistance.

Rock-paper-scissors
X-wing is unfortunately not so little like Rock-papers-scissors. Often when you reveal squads it is obvious right from the beginning who has the upper hand. Not because one squad is better but because of the fit.

Pilot Skills
If you field 3 ships with PS8 against 3 ships with PS9 you know you have a massive uphill battle to fight. Your PS8 could as well have been PS2 and it would have made no difference (except your squad would have been much cheaper). There are a few mechanism that make it convenient to have the same PS on all your ships. If both players reason like this it is very likely someone will get a PS advantage before the game even starts.

I hope 2nd Edition will be more interesting and balanced for all combinations of PS.

Turrets beat Arc Dodgers beat Jousters
X-wing was originally about choosing a maneuver template, resolving your move, and the player who outsmarted/outguessed the opponent gets an upper hand. Arc dodgers – hi PS pilots with boost and/or barrel roll turn the maneuver template into an afterthought. In order to beat a high PS arc dodger you need a turret, which reduces the role of maneuvering and flying.

I hope in 2nd Edition both Arc Dodging and Turrets will be less efficient so the game gets back to the maneuver dial.

Rebalanced Maneuver Dials
After years of Waves almost every ship has a superior maneuver dial to the T65 X-wing. It makes no sense.

I hope in 2nd Edition the maneuver dials are balanced.

2 attack dice vs 3 defence dice + evade
Some ships can hardly produce damage to other ships at all. Particularly 2 attack dice is getting hopeless against many squads. A more powerful weapon should not make it easier to hit, it should cause more damage when you hit. For the rebels this hurts the A-wing and the Z95 particularly bad.

I hope in 2nd Edition no ships will be allowed to be practically safe from 2 attack dice.

Ordnance
Torpedoes and Missiles were not good enough when the game came out. Different upgrades have tried to improve the situation so now there are some cases where ordnance can work. Harpoons are effective but there is nothing fun or thematic about them whatsoever (why do they attach if they only remove shields).

I hope in 2nd Edition Torpedoes and Missiles will be more like upgrades that improve an attack or two for for most any ships, rather than very specific strategies. I hope the different Missiles and Torpedoes will be more balanced.

Secondary Weapons
I think the costs for secondary weapons are problematic. For the X-wing, which already has a primary weapon of 3, paying 4 points for a single Torpedo that typically requires target lock often makes little sense. Also, Guidance Chips collides with other modifications.

The B-wing and Y-wing are more suitable for Torpedoes (extra munitions + guidance chips) but they have Cannon and Turret options also.

The B-wing already has 3 attack dice and usually it has other weaknesses that are more important to fix than a slightly better attack. They Y-wing on the other hand really needs a turret. So much so that TLT (or rarely Ion Turret) are almost mandatory and the weaker turrets are rarely used.

The A-wing is fun with a missile but it hardly makes sense instead of Chardaan Refit.

Secondary Weapons are too expensive to add just in case or for the fun of it. In a way I would have preferred them to be a mandatory configuration choice because it would make the game more interesting. As it is now a generic Y-wing is flown with TLT. If all generic Y-wings came both with a turret and two torpedoes of choice flying them would be much more interesting. But today you would never field such a Y-wing because it would die with most secondary weapons never used and points wasted. You only equip ordnance if you are quite sure you can deliver them very early in the game (high PS is a must).

I hope in 2nd edition more secondary weapons are brought into actual play so they create tactical choices in the game, rather than merely being strategic list building choices.

Stress as control
There are a few upgrades and pilots that can deliver stress rather arbitrarily (like Tactician and R3-A2). While a somewhat useful strategy against some opponents I don’t much enjoy this mechanism. I think it makes more sense to deliver stress with weapons like Flechette Cannon/Torpedeos, bombs and criticals.

I hope in 2nd Edition stress delivery will not be a strategy.

Regeneration
Regeneration can make a pilot practically immortal (against some opponents) and/or make the game very long. I think the idea of the game is that ships should get damage and get destroyed, not repair during battle.

I hope in 2nd Edition recovering shields will be a more limited thing.

Actions, multiple actions and free actions
It was cool that Darth Vader could make two actions and Push The Limit was also cool. But when ships start getting free actions (or tokens) it makes the game less interesting. There should be an element of guessing and risk-reward involved with actions. The worst thing is cards like Expertise.

I hope in 2nd Edition the very normal thing will be one maneuver and one action. Multiple actions should not be routine and tokens should not just come for free.

Upgrades, pilots and combos
I understand a game like X-wing is about finding powerful combination of upgrades (like in Magic The Gathering). But that also eliminates balance. Today I tried Rey+Finn+Gunner+Expertise. Finn is kind of useless in most other cases and Gunner is usually overpriced. But the combination with Rey and Expertise is very powerful. Sometimes in X-wing it is like the fundamental principles of the game are overthrown by upgrades and pilot abilities.

I hope in 2nd Edition pilot abilities and upgrades will play a less significant role for the outcome of the game. I hope the list building element is more about taste, style and tactics and less about finding very optimal and efficient combinations (because those few strong combinations of pilots and upgrades will generally rule the game and all else will turn obsolete and uncompetetive).

Cloaking
Cloaking is cool. But the idea of decloaking with a boost or barrel roll is that you didn’t really know where the cloaked ship was. It really makes no sense when a ship (Whister) cloakes and decloakes every round basically breaking all reasonable rules of flying.

I hope in 2nd Edition cloaking gets more balanced.

Generics
I think X-wing is (too) much about Aces and often pairs or triples of aces. When it comes to Generics it has often been very monotonous squads (4xY+TLT, BBBBZ).

I hope in 2nd Edition it will make sense to fly a wing leader with a few generics and that all-aces-lists will be less common (or even uncommon).

Early game vs End game
I have often fielded 4-5 generics against 2-3 aces. The game is interesting from the start. Aces can be blocked, fire can be focused on a single ace and so on. If I play well both sides have lost ships and the game is down to 2-3 generics vs a single ace. Usually the Ace wins even if it represents fewer squad points, and often the ace can control the game completely. I understand the opposite is somewhat true for Epic games: with 200-300 points per side the aces are vulnerable and not so significant. This is perhaps realistic if there is such a thing.

I hope in 2nd Edition the game will be more balanced (and interesting) from start to end.

Conclusion
It is easy to get a romantic idea about the original game with just T65 vs Tie. Of course it is more fun now with all the variety of ships, upgrades, pilots and tactics. But there are also severe balancing problems.

  • Many ships are rarely used
  • Even more pilots are never used
  • TLT is enormously dominant as turrent
  • Harpoons are very dominant as ordnance
  • Miranda is overpowered (in a K-wing of all possible ships), but she is necessary to balance out the Arc Dodgers that otherwise just beats most squads
  • Many cards have been nerfed and the original text/rules dont apply anymore
  • Powercreep – more defence dies – more attack dice – more upgrades – better maneuver dials; has turned the game more into a guessing arms race and less into a tactical flight game

A new simplified, unified and balanced edition can probably be much better.

After playing X-wing I have often thought that perhaps it would be funnier to just construct to lists that are supposed to be balanced and thematic against each other. The 2nd Edition seems to have this idea for casual game.

The conversion kits seem great (and reasonably priced). Hopefully in 2nd Edition I don’t want to play XXXX, XXXXZ, BBBBZ, YYYY, AAAAA, AAAAAA or ZZZZZZZZ but rather squads with more variety. In that case a single conversion kit will do quite fine.

Code Reuse: Generic vs Specific code

Code reuse is probably the most important key to productivity and quality when programming. Node.js is very successful, partly because NPM is very successful at facilitating simple code reuse of vast amounts of reusable packages (of various quality).

However, a project can suffer from too many (external) dependencies which can cause problems with quality, complexity, reliability, maintainability and flexibility: the problems the external code was supposed to solve, not cause.

Generic code
Being generic is generally good when it comes to code. A successful (as in many downloads) NPM library is probably quite generic (like Express, Moment or Bootstrap), otherwise it would not appeal to a large number of developers. One problem with generic functionality is that when used, it is often not the easiest and most compact way to do things.

Specific code
Being specific means that code (especially it API) is shaped exactly for the what is needed in the current project. It may not be very useful outside this project (or organisation), or most other organisations would choose do do things differently and would not agree with it. However, for the project it is being used in, it maximizes reuse.

Example: Bootstrap
Imagine you use Bootstrap and you have a lot of buttons that look the same. You use standard Bootstrap (not to confuse other people or reinvent the wheel) and may end up with exactly the following in many places:

  <button type="button" class="btn btn-outline-danger btn-sm">...

This is 60 characters, repeated exactly all over the application. How about:

  <button class="button-red">...

Now, the first is the result of using Generic and widely reusable classes. The second is the result of deciding that in this application there are a few button types only, each with a specific custom class.

The more specific way is more compact, less prone to typing mistakes and clearer. It is simply better because it maximizes reuse.

Example: Moment
Imagine in your application that in many places you produce date strings of the form “2018-12-24”. Not wanting to use the annoying (ES) standard library you use Moment.js.

  var datestr = moment(somedate).format('YYYY-MM-DD');

This is admittedly as good as a generic library gets, but if you do this in multiple places you can be more specific:

  var datestr = dateToStr(somedate);

It is clearly more compact and consistent and less prone to error. It is simply a better way to write code. The authors of Moment cant make such a specific dateToStr-function because it makes no sense to a lot of use cases. But in your project it makes a lot of sense (to effectively restrict date strings to a single format).

Making your specific choices
My point is that in your project you make specific choices and the code you write should conform to these choices automatically (by reusing your own function) not by passing (the same) arguments to functions too generic for your needs.

Wrapping or writing your own
What I find sometimes happens when I use generic code is something like:

  1. I start using it naively
  2. I get too much redundancy and my code is not as compact as I want
  3. I start wrapping the generic code with my own interfaces
  4. The generic code is not capable of what I want
  5. I extend my own interfaces to do things on their own
  6. I realise I don’t need the generic code at all

I wrote a wrapper around Angular (v1) $http because a lot of my parameters were always the same. Later I wanted to use my wrapper in an application that did not use Angular at all, so I reimplemented my wrapper using XMLHttpRequest (the JS standard library). In the end the code was just marginally larger and more complex than it was when it depended on $http and it had 0 dependencies. So now I have my own http-request-library, but it is arguably too specific and narrow for use in other places.

So one problem with using generic code (first) is that you don’t know much value it creates. I thought $http did great stuff for me, when in fact it was easily removed and I might as well have been using XMLHttpRequest from the beginning.

How much do you save?
If you want to travel from Paris to San Francisco, would you:

  • Use a free train ticket Paris-London?
  • Use a free flight ticket to Dallas?
  • Use a 25% discount coupon with Icelandic Air (flying via Reykjavik)
  • Rather be in Bogata in the first place

The fact is that if Air France sells direct tickets Paris-SF none of the above offers might really be worth it. I think it is the same with programming. Using 10 dependencies, each to save a few lines of codes, in a rather simple project, is in a way the equivalent of flying from Paris to San Francisco with 10 connections for $1.

Please notice that I don’t intend to be ridiculous about this. You should use standard browsers available, web servers, compilers, linters to check your code, an editor that makes you productive, appropriate testing tools and so on. I am not saying write everything in C or ams.js from scratch! I am saying, understand that the standard tools (browsers, Node.js) and the real published standards (ES, HTTP, HTML, CSS) offer (most) everything you actually really need. They are the equivalent of airlines, airplanes, passports and open borders: the things that make it possible for most people in the West to safely cross the Atlantic ocean for fun, something unimaginable 200 years ago. It is not the bonus programs, airport lounges or in-flight-entertainment that make a significant difference when travelling between continents.

A simple test case
I decided to write a very simple responsive web page. It allows you to enter a date and obtain the weekday. It is not a datepicker test. I use:

  • Moment to validate input date YYYY-MM-DD
  • Moment to calculate week day
  • Bootstrap to make the application responsive (it looks different on a mobile phone in portrait mode)
  • Vue.js for DOM manipulation

I then removed Bootstrap and Moment and used CSS and standard library Date instead.

When you try them I think you find that they essentially equivalent. Both are crude and require more work before the UX is perfect for all screen sizes. I did not intend the non-Bootstrap version to be an exact copy of the Bootstrap version (they both have their pros and cons).

Bootstrap: benefits and implications
For this simple application all I needed was the minimised bootstrap css (144k, larger than vue, moment and my code together), no javascript code.

With Bootstrap my CSS was 10 lines. Even for this trivial application Bootstrap did not satisfy my requirements (this may be due to my ignorance when it comes to Bootstrap). The HTML code was 37 lines.

Without Bootstrap my CSS was 39 lines and the HTML code was 27 lines. This basically means that writing my own (more specific, reusable) CSS allows for more compact and consistent HTML.

I am not saying this is real evidence for anything or that the solutions are perfectly equivalent. I am just saying that Bootstrap is not like getting from Paris to LA for free. It is more like starting in London instead of Paris. And you will hardly write more compact HTML with Bootstrap then you would with a well crafted project specific CSS.

Moment.js: benefits and implications
I will just show the code. With Moment:

      function dateValidate(d) {
        return d === moment(d, 'YYYY-MM-DD').format('YYYY-MM-DD');
      }
      function dateToWeekday(d) {
        return moment(d, 'YYYY-MM-DD').format('dddd');
      }

As you can see, I wrapped Moment to make the component code cleaner. Using standard library Date instead of Moment:

      function zPad(x,l) {
        var r = '' + x;
        while ( r.length < l ) r = '0' + r;
        return r;
      }
      function jsDateToStr(d) {
        return zPad(d.getFullYear(),4) + '-'
             + zPad(d.getMonth()+1 ,2) + '-'
             + zPad(d.getDate()    ,2);
      }
      function strToJsDate(s) {
        return new Date( +(s.substr(0,4))   ,
                         +(s.substr(5,2))-1 ,
                         +(s.substr(8,2)) );
      }
      function dateValidate(d) {
        return d === jsDateToStr(strToJsDate(d));
      }
      function dateToWeekday(s) {
        return ['Sunday','Monday','Tuesday','Wednesday','Thursday',
                'Friday','Saturday'][strToJsDate(s).getDay()];
      }

In a real project you would probably have a pad-function available but now I wrote one. And perhaps there are better ways to use the standard library.

My point here is that if you don’t do much Date-manipulation, using Moment eliminates 10 lines of code (at the cost of an external dependency of 51k minimized). These 10 lines of code are something every programmer should be very capable of writing, they are easily testable, and highly reusable.

Vue.js
How about eliminating Vue.js as well? The ironic thing is that I don’t know how to do direct DOM manipulation (with or without JQuery). So I just presume that vue.js is worth it at 87k minimized.

If I did know how to eliminate Vue.js I would at least have a clue about what its value actually is. Now I just trust I am better off with it than without it. And that is what I encourage you not to do about every external dependency that could be used in your project.

More Reading
I found this blog post interesting.

BTW: Bootstrap sucks
I am not claiming that my no-bootstrap-version is perfect. But I think Bootstrap gets responsive UX wrong. My little appliation looks ridiculous on a really wide screen. I don’t need room for more than 10 characters, and the buttons don’t need to be spread out. A good responsive design reorganises blocks of content without changing the size of elements such as buttons.

BTW: Moment is slower
I made some benchmarks of my date validation functions based on Moment and based on Standard Library. Depending on Moment roughly doubled execution times. On my Chromebook I could do about 10000 validations per second, which is not a huge number. There might be better ways to check if a date is valid (both for Moment and Standard Library) so perhaps this is nonsense.