Thursday, 9 May 2019

50 tactical and strategic blunders in the battle of Winterfell


Yes, I know Game of Thrones is a fantasy drama television series. But still analysing battle tactics is a lot of fun.

  1. Trebuchets (long distance catapults) placed in front of infantry (to be abandoned early in the battle).
  2. Trebuchets or catapults placed outside the fortress rather than on higher ground to achieve longer distance and to protect the equipment.
  3. Not employing more catapults that could be directed towards enemy hot spots. (could be operated by civilians)
  4. Not using Trebuchets and catapults constantly to bombard enemy. 
  5. Not using archers extensively.
  6. Not filling castle walls to the full with archers or other combatants, with backup forces.
  7. Not ordering all humans to contribute in creating more trenches, spike obstacles etc. to gather stones for catapults and wall defences etc. The defenders had for weeks known the Night King was on his way. Better defences could been planned weeks in advance. 
  8. Not using dragons from the start for air raids. (While having a two-to-one air superiority)
  9. Not weaponizing dragons. Dragons probably don't have unlimited fire breath. Could therefore also utilise weapons such as large nets or chains held between the two dragons used to swoop along the battle field to wipe out the dead. (Like fishing trawlers). 
  10. Not using dragons for high altitude bombing (out of range of ice javelins etc, before snowstorm)
  11. Humans initiating the battle during night. Should have waited as long as possible until morning light. (The dead probably have better night vision)
  12. Not heavily armouring Dothraki cavalry when used as a charging force. 
  13. Using Dothrakis in a frontal assault shock tactic (knowing this would not create any fear or confusion on this type of army).
  14. Cavalry charging too far away from communication distance with commanders.
  15. Dothraki cavalry not used on the flanks, where they would have space to manoeuvre. 
  16. Dothraki force attacking head on without any rear support.
  17. Dothraki force charging straight into unknown territory. (poor sight, not knowing what awaited them)
  18. The army of the dead not besieging the castle from a distance. Why hurry when you are already dead and don't need food. 
  19. Weak central command. Military leader Jon Snow not in control being on a dragon. 
  20. Few signals being used (flags and horns etc) to control the battle.
  21. Tacticians like Tyrion Lannister hiding away in a crypt.
  22. Commanders placed in the front of their forces exposed (Brienne, Jorah, Greyworm etc)
  23. Not using flaming oil down the side of the castle walls. (if not effective against wights, it would at least provide more light)
  24. No moat in front of castle wall.
  25. Not placing as many as possible of the Winterfell fighters inside the castle.
  26. Burning spikes placed behind army rather than in front. Infantry should have been placed behind burning spikes/trenches, picking off the undead that made it past. 
  27. Not using more than one line of spike trenches (obstacle perimeters).
  28. Not using burning oil pits, pitfall traps etc.
  29. Not using wall climbing deterrence devices to push climbers off side of wall.
  30. Not creating bottleneck entrapment areas neither outside of castle or inside (Army of dead consist of very stupid fighters and could be funnelled into a passage where they could be picked off).
  31. Not using ice dragon or catapults to drop diseased animals, corpses of plague victims or other contagious agents into the castle, then sit back and wait for humans to die of disease. (biological warfare)
  32. Not taking into account strength and weaknesses of opponent. The dead don't have fear, you can't change their fighting morale, they don't get tired etc.
  33. Not using guerrilla tactics before the battle. The wights are stupid and not very aware of their surroundings. Hit and run tactics could have been used over weeks leading up to the main battle. Dothrakis would be perfect for this. 
  34. Dothrakis not using bows or spears to fight the dead army from a distance. 
  35. Night King not situated far from the front line. He must have known that if he died all the other goons would be exterminated.  
  36. Not having better communications (horns, whistles etc) to gather and surround the Night King for a coordinated strike. 
  37. Poor planning. The battle plan seem to have been laid down in one evening. Should have spent more time also making a plan B, also exploring different scenarios, evaluating risks etc. 
  38. No plans for what to do when walls got breached.
  39. Winterfell defenders not sharing knowledge about decapitating, using dragonglass, etc. to avoid newly dead being raised to fight again later on in the same battle for the other side. 
  40. Scouts not employed to gain intelligence on the attackers in the days before the battle. 
  41. Dragons not used to conduct reconnaissance of enemy lines.
  42. No backup plans for lighting up the fire trenches.
  43. Not firing arrows and spears or poking javelins at the undead on the other side of the burning trenches. 
  44. Not prioritizing locating and killing a Walker over a wight, and the Night King over a Walker.
  45. Landing a dragon on the battlefield (to be overrun and held down by wights).
  46. Not planning how to use special forces (such as Arya).
  47. The dead not using anti-aircraft "artillery" more extensively to try kill dragons.
  48. Not using snipers to fire Valyrian steel tipped arrows at Night King.
  49. Not creating smoke above the castle to reduce sight for the ice dragon when attacking the castle.
  50. Not creating trap rooms to be set on fire etc. (See also curtain walls and murder holes) Have enemy storm a hall then close off hall at both ends using iron fences that drop down from ceiling cutting off all exits. Then set fire.
  51. Not sending woman, children and the old out of the castle to hide away far from the battle. This would leave warriors with more space to manoeuvre and would help avoid distractions. Would also be helpful in case of long sieges when food may run out.





Thursday, 21 February 2019

User friendly error messages from APIs

Error messages from API’s are typically provided in three different ways:
  • As part of the HTTP header using HTTP status code. 
  • As part of the response body. 
  • As a combination of the above, using a small subset of HTTP status codes with an emphasis on the response body as the main source of the error information. 
I have encountered all patterns above of providing errors from APIs. Over time I have come to the conclusion that the best option is the last one, combining both an error response message object and HTTP status codes (with a strong emphasis on using the response body as the main source of the error and the HTTP status code more for technical system infrastructure related errors).

Example

HTTP/1.1 401 Unauthorized
{
  "error": 567, //internal error code
  "message": "Invalid credentials",
  "description": "The provided authentication credentials were invalid." //what to do to fix it
  "infoUrl" : "https://wiki.yourwiki.com/how-to-deal-with-error-567"  //optional
  "context" : "project: ABC123, project status: draft, panelist: 123456" //optional
  "status":"401" //same as http header status incase a proxy server has messed it up etc.
  "version": "10.2.0.0" //optional
  "correlationId" : "guid" //optional, used to track events across multiple remote systems
}


Below are some benefits of providing an error response message object rather than providing HTTP status codes or other http headers alone.

From the point of view of the developer using the API 

  1. You will always know where to find the error (the response body. You can reuse same error handling code for all of the API). 
  2. Easier to see actual error when testing the API. (using tools like postman you usually first look at the body response). 
  3. New developers using the API may not know where to find the detailed error message without reading the API docs, had the error message been rendered in some special header property. 
  4. Less chance of bugs. If you instead had to rely on HTTP status codes only, then the same HTTP codes would be reused for many error situations.  
  5. You can get more detailed and structured error info from the API that will save you time when debugging. 
  6. Can also be used by very inexperienced developers that don’t know how to check HTTP status code, or by developers that use outdated or poorly designed components that can't read the header status code. 
  7. In special performance optimisation situations you don’t have to read and parse response body. You can just get header status code. 
  8. HTTP status codes (3xx, 4xx and 5xx) are not useful codes or categorisations for the end users (human using your application). By having access to more meaningful error message objects you can more easily present meaningful errors to the end user, spending less time trying to map HTTP status codes to human readable error messages in the user interface.

From the point of view of the developer creating the API 

  1. You save time not having to try to decide and pick the most meaningful HTTP status code. Business domain errors very often don’t map well to a HTTP status code. 
  2. By using both HTTP status codes and body JSON you can more easily split general technical errors from domain related errors. The HTTP status would mostly be set using this decision tree and you can provide domain related error info in the body. 
  3. Some errors can’t even be meaningfully categorised with a HTTP status code. 
  4. In some special cases there might be too many different errors possible and there aren’t enough meaningful HTTP status codes, unless you define new HTTP status codes that are not in the HTTP protocol
  5. In some cases one request could lead to several errors and it would be difficult to squeeze those into one HTTP header error field and assigning it one HTTP status code. 
  6. Extensibility. Using the body you can have several properties more easily visible (in one JSON object response) allowing you to add more error properties such as ErrorCode and ErrorCodeCategory. This could be very useful for other systems (such as in a microservices environment) to automatically display client errors in certain ways or handle similar errors of same category in some way. You could also have Severity level etc. as a property. This property could be used to decide how it is logged at the API consumer, or how it is displayed on screen etc. A context property returning some state or additional info can be helpful if the error is being logged by the consuming system. (Will help cross system debugging) You could even provide a wiki-page-link etc. to read more about how to deal with the error. 
  7. Application monitoring. Some Application Monitoring (APM) systems will record all but status 2xx as an anomaly. If you instead are providing the error code as part of the message body you may avoid filling up logs with responses that are not really errors. For example: If you have an API for purchasing stuff there is going to be all kinds of business related error messages that are just expected errors. E.g. If a product is out of stock it's not really an error, but a negative purchase outcome that is expected from time to time.   

What others are doing

GraphQL 

https://facebook.github.io/graphql/June2018/#sec-Errors   (always returns http 200 for all errors)

{
  "errors": [
    {
      "message": "Name for character with ID 1002 could not be fetched.",
      "locations": [ { "line": 6, "column": 7 } ],
      "path": [ "hero", "heroFriends", 1, "name" ],
      "extensions": {
        "code": "CAN_NOT_FETCH_BY_ID",
        "timestamp": "Fri Feb 9 14:33:09 UTC 2018"
      }
    }
  ]
}

ODATA

http://docs.oasis-open.org/odata/odata-json-format/v4.0/errata02/os/odata-json-format-v4.0-errata02-os-complete.html#_Toc403940655 (uses http status codes 4xx and 5xx)

{
  "error": {
    "code": "501",
    "message": "Unsupported functionality",
    "target": "query",
    "details": [
      {
       "code": "301",
       "target": "$search"
       "message": "$search query option not supported",
      }
    ],
    "innererror": {
      "trace": [...],
      "context": {...}
    }
  }
}

Json:api 

https://jsonapi.org/examples/#error-objects-error-codes   (combines https status code and body response)

HTTP 422 Unprocessable Entity
{
  "jsonapi": { "version": "1.0" },
  "errors": [
    {
      "code":   "123",
      "source": { "pointer": "/data/attributes/firstName" },
      "title":  "Value is too short",
      "detail": "First name must contain at least three characters."
    },
    {
      "code":   "225",
      "source": { "pointer": "/data/attributes/password" },
      "title": "Passwords must contain a letter, number, and punctuation character.",
      "detail": "The password provided is missing a punctuation character."
    },
   {
      "code":   "226",
      "source": { "pointer": "/data/attributes/password" },
      "title": "Password and password confirmation do not match."
    }
  ]
}