- Simplicity > cleverness
- Do one thing well per unit (fn/class/module)
- Data first; make invalid states unrepresentable
- Composition > inheritance
- Accept minimal interfaces, return concrete types
- Tiny public API
This document captures the core principles and beliefs that guide how Rob Pike approaches software design and implementation. These rules form the foundation for all code decisions in this project.
- Simple is not easy. Simple means having fewer parts, fewer concepts, fewer moving pieces.
- Clear is better than clever. Code should be obvious to read and understand.
| # module.app_dbs.google_sql_database.app will be created | |
| le-beta_v3.7.0_x5: 2020/02/12 14:36:34 [INFO] Instantiating Google Cloud Spanner client for path https://spanner.googleapis.com/ | |
| + resource "google_sql_database" "app" { | |
| 2020-02-12T14:36:34.149+0100 [DEBUG] plugin.terraform-provider-google-beta_v3.7.0_x5: 2020/02/12 14:36:34 [INFO] Instantiating Google Cloud Dataproc client for path https://dataproc.googleapis.com/ | |
| 2020-02-12T14:36:34.149+0100 [DEBUG] plugin.terraform-provider-google-beta_v3.7.0_x5: 2020/02/12 14:36:34 [INFO] Instantiating Google Cloud Dataproc Beta client for path https://dataproc.googleapis.com/ | |
| 2020-02-12T14:36:34.149+0100 [DEBUG] plugin.terraform-provider-google-beta_v3.7.0_x5: 2020/02/12 14:36:34 [INFO] Instantiating Filestore client for path https://file.googleapis.com/ | |
| 2020-02-12T14:36:34.149+0100 [DEBUG] plugin.terraform-provider-google-beta_v3.7.0_x5: 2020/02/12 14:36:34 [INFO] Instantiating Google Cloud IoT Core client for path https://cloudiot.googleapis.com/ | |
| 2020-02-12T1 |
| {"lastUpload":"2021-08-01T16:54:58.756Z","extensionVersion":"v3.4.3"} |
We should always use ArrayList when we need a List, except for a few use cases where LinkedList is more adapted (when implementing a queue for example). We should also avoid using Vector which is a legacy class. If we need synchronisation, we will use the Collections.synchronizedList wrapper.
| Method | ArrayList | LinkdedList |
|---|---|---|
get(int i) |
O(1) | O(n/4) |
add(E e) |
O(1), O(n) worst-case | O(1) |
You mention cutting with yy and complain that you almost never want to cut whole lines. In fact programmers, editing source code, very often want to work on whole lines, ranges of lines and blocks of code. However, yy is only one of many way to yank text into the anonymous copy buffer (or "register" as it's called in vi).
The "Zen" of vi is that you're speaking a language. The initial y is a verb. The statement yy is a synonym for y_. The y is doubled up to make it easier to type, since it is such a common operation.
This can also be expressed as dd P (delete the current line and paste a copy back into place; leaving a copy in the anonymous register as a side effect). The y and d "verbs" take any movement as their "subject." Thus yW is "yank from here (the cursor) to the end of the current/next (big) word" and y'a is "yank from here to the line containing the mark named 'a'."
If you only understand basic up, dow
- We can use different ways to configure an app: local/global variables, flags, environment variables, config files.
- Solutions like viper exist for go apps to combine those solutions all together.
- Should we use environment variables for app configuration?
In my opinion, all the OS-dependent configuration options should be passed explicitly at the start of the application. Flags are the perfect way for that, because on the contrary of env variables, it's os-independent and explicit.
Here are all the reasons why we shouldn't use environment variables:
Dynamically set: they can be set by other users, so we are not really sure of their value across the time.
| var ( | |
| cursor int64 | |
| items []string | |
| ) | |
| results := make([]string, 0) | |
| for { | |
| values, err := redis.Values(conn.Do("SSCAN", key, cursor)) | |
| if err != nil { |