Becoming a backend developer - Part 1: Foundational concepts
You need experience in at least one of Android, iOS or Flutter development.
This is a guide for mobile app developers. In this three-part series we will cover all the basics of what it takes to become a backend developer.
- Part 1: Foundational concepts
- Part 2: Building the server
- Part 3: Connecting to the server from a mobile app
Introduction
So you have some experience developing mobile apps for Android or iOS. You may even have a few apps on Google Play or in the App Store. More and more, though, you are getting ideas for new apps that would require a server backend. The problem is that you don’t know how to do server programming. Maybe you work for a small company or maybe you’re on your own, and you don’t have the resources to hire a backend developer. Now you’ve decided that it’s finally time to take the leap and learn how to do it yourself. If that’s you, then you’ve come to the right place.
In this series I will take you through everything you need to know to get started building a backend server and connecting it to your mobile apps. There are a myriad of choices of platforms and frameworks for both the backend and frontend. I will show you how to build two backend servers (Node.js and Server-Side Dart) and three frontend apps (Android, iOS, and Flutter). Choose one backend server and one frontend app to follow along with.
The purpose of telling you how to do the same thing on different platforms is so that you can see that the process is basically the same no matter what you choose. Even if you decide on a different technology, you can still follow along and just Google how to adapt it to your particular situation.
No matter what platforms you choose for your backend and frontend, there are a few foundational topics related to client-server communication that are important to know. They include URIs, HTTP, REST APIs, and JSON. If you are already familiar with these topics, feel free to skip directly to Part 2: Building the server.
URI
A URI (Uniform Resource Identifier) is an address for a resource. A resource, for example, could be a webpage or a file or a database row. A specific type of URI is a URL. (See difference between URI, URL, and URN.) You’re probably familiar with URIs from your mobile app development and certainly familiar with URLs from web browsers, but you might not be aware of their components, especially the query string.
The query string starts with a ?
question mark and is followed by parameters. The parameters are separated by &
ampersands. So in the example above we have two parameters:
q = flutter
language = en
See this page for more explanation about the parts of a URI.
URI example
When our client app accesses resources on our server, it will use a URI to reference them. Here is an actual example that we will use:
http://localhost:3000/0
I’ll talk about the http
protocol part of the URI in the next section. We’ll be using localhost
(that is, 127.0.0.1
) to refer to our own machine, where the server will be running. This will simplify the development process. Then we will (somewhat arbitrarily) choose port 3000
to communicate over. Our path is simply the root /
. We could have used something like /fruit
or /items
. In fact, a more complex server app would probably define several different paths (also known as routes) that clients could connect to to access different types of resources. In our minimal server, though, we’ll just use one path. The final 0
at the end of the path will be used as a parameter to refer to the ID of a database row. (Actually for us it will refer to the index of an array that is pretending to be a database, but the client doesn’t have to know that.)
HTTP
HTTP (Hypertext Transfer Protocol) is a set of rules for how to transfer data on the web. You’ve seen http://
in web addresses, of course. Now you’re going to use the same protocol to transfer data between your app and the server.
Verbs
The primary HTTP verbs that we are going to be using are:
GET
- for requesting data from the serverPOST
- for sending new data to the serverPUT
- for updating data on the server (fully replace an existing resource)PATCH
- for updating data on the server (partially modify an existing resource)DELETE
- for deleting data on the server
You will note that these are very similar to the CRUD operations of a database:
- Create ->
POST
- Read ->
GET
- Update ->
PUT
orPATCH
- Delete ->
DELETE
These HTTP verbs are sent by clients to the server. This is known as a request. After the server receives a request it processes it and then sends back a response to the client. Both the request and the response contain metadata known as headers. The primary data itself is sent in the body.
Status codes
One of the headers is the status code. When a client makes an HTTP request, the server should send back an HTTP status code in its response. This lets the client know if the request was successful or not. You’ve seen the 404 Not Found response whenever you click on a broken link. Here are some more that you should get familiar with:
-
1xx Informational
-
2xx Success
- 200 OK - 201 Created
-
3xx Redirection
- 301 Moved Permanently
-
4xx Client Error
- 400 Bad Request - 401 Unauthorized - 403 Forbidden - 404 Not Found
-
5xx Server Error
- 500 Internal Server Error - 502 Bad Gateway
It’s your responsibility as a backend developer to choose the right code to add in your response to a client request. You can read more about HTTP status codes here and here.
Content type
Another header is Content-Type
, which is the Media Type (formerly known as MIME type). This tells us the type of data that is in the body. It could be plain text or HTML or JSON. Here are a few examples as they look encoded:
application/json
application/x-www-form-urlencoded
image/png
text/plain
text/html
Here is a complete list. We will be using JSON ( application/json
) primarily. I’ll explain it more in a little while.
Examples
Let’s look at a few examples of the raw text of some HTTP requests. The following is a GET request:
GET 3000/0
Content-Type: application/json
cache-control: no-cache
Postman-Token: 00572d5b-a2ec-4195-8436-ef1e797c0751
User-Agent: PostmanRuntime/7.6.0
Accept: */*
Host: localhost:3000
accept-encoding: gzip, deflate
Notice that it starts with the HTTP verb and URI path. The rest of the lines here are headers. I used Postman to make the request so that I could get the raw text.
This is the response that the server gave to that GET request:
HTTP/1.1 200
status: 200
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 31
ETag: W/"1f-xulzIcqO6GqXGwKlplM3A8YgRg8"
Date: Fri, 08 Mar 2019 19:30:16 GMT
Connection: keep-alive
{"fruit":"apple","color":"red"}
You can see that the status code is 200. Everything is OK. The content type of the body is JSON. You can find the body at the end, separated from the headers by a single blank line.
Here is a POST request:
POST 3000
Content-Type: application/json
cache-control: no-cache
Postman-Token: 6b985c28-ef59-4dac-930c-63b3245de3f1
User-Agent: PostmanRuntime/7.6.0
Accept: */*
Host: localhost:3000
accept-encoding: gzip, deflate
content-length: 46
{ "fruit": "kiwi", "color": "purple" }
And here is the response from the server:
HTTP/1.1 200
status: 200
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 20
ETag: W/"14-gSUAeNN7vCHjCoiKRj0ziSuiiQI"
Date: Fri, 08 Mar 2019 19:34:18 GMT
Connection: keep-alive
Item added with id 2
You don’t need to understand the details of all that raw text. The frameworks that we are going to use to interact with the HTTP protocol will hide most of it from us. I just share these examples with you to let you know what is happening under the hood. If you do need to get at the headers, though, you will be able to access them from within the framework.
REST API
REST
When we do our client-server communication, we will be using what is called a REST (or RESTful) API. (REST stands for Representational State Transfer, but I’ve never found it very helpful to know that.) In addition to using the HTTP protocol, REST adds some additional rules for how the client and the server should interact. As a beginner, remember these important REST principles:
- The server should not save any state about a client.
- Only use the HTTP verbs as they are defined. For example, while it is technically possible to create a resource on the server by sending the data through a GET request, REST says we should use a POST request for creating new resources.
There is a lot more to REST, but you don’t need to understand everything right now. Check out this and this if you are interested.
API
The API is the set of methods that we will handle on the server. It’s our own personal protocol for communicating between the client and the server. Once we have our API defined, it doesn’t matter what is running on the server or who the clients are. This is a prime example of clean architecture.
Our API
The REST API is defined in terms of HTTP verbs ( GET
, POST
, PUT
, etc.) along with a URI path. This is the API that we will use for our server and clients in the second and third parts of this series:
GET http://localhost:3000/ // get all items
GET http://localhost:3000/id // get item at id
POST http://localhost:3000/ // create new item
PUT http://localhost:3000/id // replace item at id
PATCH http://localhost:3000/id // update item at id
DELETE http://localhost:3000/id // delete item at id
JSON
When communicating with a server we need to pass data back and forth. This becomes more difficult when we want to pass complex objects (that is, most anything besides strings, numbers, and booleans). Since we can’t pass an object directly using in the HTTP protocol, we can convert it to a string (also known as serialization), transfer it in the body of an HTTP message, and then convert it from a string back to an object.
A common way to do that is with JavaScript Object Notation (JSON). We’re not limited to JavaScript, though. There are JSON libraries for Java, Kotlin, Swift, Objective-C, Dart, and many other languages.
Example
JSON formats the data in a class to a list of key-value pairs. Here is what a simple User object would look like when converted to JSON:
{
"id" : 3,
"name" : "Mary",
}
Notes:
- The curly braces represent an object.
- The keys and any string values need double quotes. Other values don’t.
- JSON encodes objects, arrays, strings, numbers, booleans, and nulls.
- Objects and arrays can be nested.
- See the documentation for a full explanation. Here are a few more examples.
White space does not matter. So this:
{"fruit":"apple","color":"red"}
is the same as this:
{
"fruit": "apple",
"color": "red"
}
In a model object
When you create a model object, it’s convenient to add a constructor and helper method that can serialize and deserialize (encode and decode) between the object and JSON. For example, here is a model object in Dart. The constructor creates an object from a JSON map. And a JSON map can be created from the object using the toJson()
method.
class Fruit {
int id;
String fruit;
String color;
Fruit(this.fruit, this.color);
// named constructor
Fruit.fromJson(Map<String, dynamic> json)
: fruit = json['fruit'],
color = json['color'];
// method
Map<String, dynamic> toJson() {
return {
'fruit': fruit,
'color': color,
};
}
}
As I said, all of the platforms and languages have libraries for converting between a raw JSON string (which is what you have in the HTTP body) and a Map or Dictionary or whatever key-value data structure is used in your language.
Conclusion
You now have all of the basic background knowledge you need to start building your backend server. In part two I’ll show you how to make the server, and in part three we’ll make a simple frontend app to connect to the server. These will implement the REST API that we learned about above.
The code for the servers and for the frontend apps is on GitHub.
19 March 2019
by Suragch