Giter VIP home page Giter VIP logo

dive's Introduction

Motivation

  • Awesome snippets
  • TILs

Note to the readers

  • Browse for the issues
  • Labels might help you to drill down further

dive's People

Contributors

amitkumardas avatar

Watchers

 avatar

dive's Issues

api names: experiment with the design with flexibility in mind

  • Put some futuristic constraints early on to get to better designs & names
  • List down all the alternatives & take a decision
  • Last updated date: 15/JUL/2024

Attempt 1

package carvelgen

func Bundle(specs BundleSpecs) (BundleResult, error)
func NestedBundle(specs BundleSpecs) (NestedBundleResult, error)

Attempt 2

package carvelgen

type AnyBundle interface {}

// Bundle is the entity name
var _ AnyBundle = BundleSpecs{}

// NestedBundle is fit to be considered as the entity name
// Note: It is important to avoid considering `Nested` as a behaviour
// Note: `Nest` can be considered as behaviour
// Note: `Nested` can be considered as the state of the entity 
var _ AnyBundle = NestedBundleSpecs{}

// Bundle creates a new bundle
// Nice: No need for NestedBundle API
func Bundle(specs AnyBundle) (BundleResult, error)

Attempt 3

// Package carvel deals all things about carvel 
// Note: Removed `gen` suffix. 
// Note: It is not good practice to tie behaviour & entity together to name a package
// Note: Package `carvelgen` can not expose List, Get, Delete etc. APIs
package carvel

// NewBundle creates a new package bundle instance
// Idiomatic: NewXXX implies creating a memory object
// Avoid: NewPackageBundle etc. since carvel folks can understand without the extra bits
func NewBundle()

// CreateBundle creates a new bundle in the PWD with .tar.gz as the file extension
// Note: CreateBundle differentiates clearly from NewBundle
func CreateBundle()

// GetBundle fetches the bundle as a file from Gobuild, Artifactory, etc.
// Note: The specifics of fetching from Gobuild or Artifactory is handled via Specs
// E.g.: GobuildBundleGetSpecs, ArtifactoryBundleGetSpecs
//
// Even better with GobuildBundleSpecs, ArtifactoryBundleSpecs, etc.
// Since it is best to avoid attaching behaviour with entity to name another entity
func GetBundle()

// DeleteBundle deletes the bundle from Gobuild, Artifactory, etc.
// Note: The specifics of deleting the exact bundle from Gobuild or Artifactory
// is handled via Specs
// E.g.: GobuildBundleSpecs, ArtifactoryBundleSpecs
func DeleteBundle()

// ListBundle lists the bundles from artifactory, gobuild, etc.
// Note: The specifics of listing from Gobuild, Artifactory, etc is handled via Specs
// E.g.: GobuildBundleSpecs, ArtifactoryBundleSpecs
func ListBundle()

Attempt 4

  • file: relm/pkg/carvel/bundle.go
package carvel

// Note: Single method contract per API
type AnyBundleNew interface {
  newBundle()
}

type AnyBundleCreate interface {
  createBundle()
}

type AnyBundleGet interface {
  getBundle()
}

// Notes:
// - Single specs for all contracts wherever possible
// - One or more specs for all contracts if required
// - `Action` field will help switch to the exact contract method
// - `State` [optional] field further allows to switch logic per action

var _ AnyBundleNew = BundleSpecs {} // Action: New

var _ AnyBundleCreate = BundleSpecs {} // Action: Create
var _ AnyBundleCreate = PackageCRBundleSpecs {} // Action: Create
var _ AnyBundleCreate = GobuildBundleSpecs {} // Action: Create
var _ AnyBundleCreate = ArtifactoryBundleSpecs {} // Action: Create
var _ AnyBundleCreate = BuildsquidBundleSpecs {} // Action: Create

var _ AnyBundleGet = GobuildBundleSpecs {} // Action: Get
var _ AnyBundleGet = ArtifactoryBundleSpecs {} // Action: Get

var _ AnyBundleList = GobuildBundleSpecs {} // Action: List
var _ AnyBundleList = ArtifactoryBundleSpecs {} // Action: List

var _ AnyBundlePush = ArtifactoryBundleSpecs {} // Action: Push
var _ AnyBundlePush = DevArtifactoryBundleSpecs {} // Action: Push
var _ AnyBundlePush = CDNBundleSpecs {} // Action: Push

/*
  These signatures say it all
 */

func CreateBundle(specs AnyBundleCreate) (BundleResult, error)
func GetBundle(specs AnyBundleGet) (BundleResult, error)
func ListBundle(specs AnyBundleList, more ...AnyBundleList) (BundleResult, error)
func DeleteBundle(specs AnyBundleDelete) (BundleResult, error)
func PushBundle(specs AnyBundlePush) (BundleResult, error)
func NewBundle(specs AnyBundleNew) (Bundle, error) // * Bundle, not BundleResult

nix build "nixpkgs#bat" results in SSL peer certificate or SSH remote key was not OK (60)

% nix build "nixpkgs#bat"
warning: error: unable to download 'https://channels.nixos.org/flake-registry.json': SSL peer certificate or SSH remote key was not OK (60); retrying in 343 ms
warning: error: unable to download 'https://channels.nixos.org/flake-registry.json': SSL peer certificate or SSH remote key was not OK (60); retrying in 692 ms
warning: error: unable to download 'https://channels.nixos.org/flake-registry.json': SSL peer certificate or SSH remote key was not OK (60); retrying in 1156 ms
warning: error: unable to download 'https://channels.nixos.org/flake-registry.json': SSL peer certificate or SSH remote key was not OK (60); retrying in 2267 ms
error: unable to download 'https://channels.nixos.org/flake-registry.json': SSL peer certificate or SSH remote key was not OK (60)
# Note: same error for below command as well
% nix shell nixpkgs#curl

go design: SOLID vs functional options

Use functional options when:

  • The behaviour needs to be tweaked
    • E.g.: DryRun, Debug, UseHttp, IgnoreChecks, etc.
    • E.g.: Support reuse a cached build as well as build always features
  • TIP: API needs boolean flags & optional features
  • TIP: Remember functional options is often used with variadic arguments
    • I.e.: There can be no args or a bunch of them & both of these should be perfectly valid
  • TIP: It is wrong if clients have to remember which functional option is mandatory vs. optional

Do not use functional options when:

  • Multiple behaviours are desired
    • Github release vs Gitlab release
  • Main actor / entity changes or requires additional entities/actors
    • Running on Mac vs Running on Windows
  • More examples:
    • Save file to Database vs. Publish file to CDN
    • Build using make vs. Build using make inside container
    • Build inside container vs. Build inside K8s Pod
    • Build inside Gitlab runner vs. Build inside Jenkins runner
  • Use of functional options in above case leads to:
    • [1] A single structure that caters to all possible requirements
    • [2] Explosion in the number of functions exposed from a single package
    • Most importantly the Single Responsibility Pattern (i.e. S in SOLID) is violated due to [1]
  • Summary: Functional options is not right if it breaks any of the SOLID principles
  • Remedy: Stick to old school patterns, idiomatic & effective practices
  • Test: Keep verifying the implementations against SOLID principles

go mod download -json

% go mod download -json xyz.com/abc/machinery/tests@latest
{
	"Path": "xyz.com/abc/machinery/tests",
	"Version": "v0.0.0-20240621154238-10c32a43145c",
	"Query": "latest",
	"Info": "/Users/amitd2/go/pkg/mod/cache/download/xyz.com/abc/machinery/tests/@v/v0.0.0-20240621154238-10c32a43145c.info",
	"GoMod": "/Users/amitd2/go/pkg/mod/cache/download/xyz.com/abc/machinery/tests/@v/v0.0.0-20240621154238-10c32a43145c.mod",
	"Zip": "/Users/amitd2/go/pkg/mod/cache/download/xyz.com/abc/machinery/tests/@v/v0.0.0-20240621154238-10c32a43145c.zip",
	"Dir": "/Users/amitd2/go/pkg/mod/xyz.com/abc/machinery/[email protected]",
	"Sum": "h1:a9eRHP4rqAvXL97kUU52w+n6wXyICaPo07Iptx/pweg=",
	"GoModSum": "h1:hC1nTT4lyDmWCIjXfvQQZm3lETWhfBQUpVkFBbbb3zI=",
	"Origin": {
		"VCS": "git",
		"URL": "https://xyz.com/abc/machinery.git",
		"Subdir": "tests",
		"Hash": "10c32a43145c3dae237cebcf75f95a59a33a4918",
		"TagPrefix": "tests/",
		"TagSum": "t1:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
		"Ref": "HEAD"
	}
}
ls -ltr ~/go/pkg/mod/cache/download/xyz.com/abc/machinery/tests/@v/
total 104
-rw-r--r--  1 amitd2  staff    245 24 Jun 07:44 v0.0.0-20240621154238-10c32a43145c.info
-rw-r--r--  1 amitd2  staff   3484 24 Jun 07:44 v0.0.0-20240621154238-10c32a43145c.mod
-rw-r--r--  1 amitd2  staff     35 24 Jun 07:44 list
-rw-r--r--  1 amitd2  staff      0 24 Jun 07:44 v0.0.0-20240621154238-10c32a43145c.lock
-rw-r--r--  1 amitd2  staff  34205 24 Jun 07:44 v0.0.0-20240621154238-10c32a43145c.zip
-rw-r--r--  1 amitd2  staff     47 24 Jun 07:44 v0.0.0-20240621154238-10c32a43145c.ziphash
% ls -ltr /Users/amitd2/go/pkg/mod/xyz.com/abc/machinery/[email protected]
total 40
-r--r--r--  1 amitd2  staff   833 24 Jun 07:44 Makefile
-r--r--r--  1 amitd2  staff   328 24 Jun 07:44 README.md
-r--r--r--  1 amitd2  staff  3484 24 Jun 07:44 go.mod
-r--r--r--  1 amitd2  staff  5796 24 Jun 07:44 go.sum
dr-xr-xr-x  7 amitd2  staff   224 24 Jun 07:44 internal

go test: idea: f vs anonymous struct

package logstorage

import (
  "testing"
)

func TestLogfmtParser(t *testing.T) {
  f := func(given, want string) {
    t.Helper() // to get the test case's exact loc
  
    p := getLogfmtParser()
    defer putLogfmtParser(p)
    
    p.parse(given)
    got := MarshalFieldsToJSON(nil, p.fields)
    if string(got) != want {
      t.Errorf("MarshalFieldsToJSON [%s]:\ngot:%s\nwant:%s\n", given, got, want)
    }
  }
  
  // f(given, want)
  f(``, `{}`)
  f(`foo=bar`, `{"foo":"bar"}`)
  f(`foo="bar=baz x=y"`, `{"foo":"bar=baz x=y"}`)
  f(`foo=`, `{"foo":""}`)
  f(`foo`, `{"foo":""}`)
  f(`foo bar`, `{"foo":"","bar":""}`)
  f(`foo bar=baz`, `{"foo":"","bar":"baz"}`)
  f(`foo=bar baz="x y" a=b`, `{"foo":"bar","baz":"x y","a":"b"}`)
  f(`  foo=bar  baz=x =z qwe`, `{"foo":"bar","baz":"x","_msg":"z","qwe":""}`)
}

go: test: table vs fn: t.Helper

func TestStringsIndex(t *testing.T) {
  // Notice:
  // - No need of test struct definitions
  // - The args to f can be thought of as following:
  //   - First few args are given conditions
  //   - Last arg is always the want condition
  f := func(s, substr string, nExpected int) {
    t.Helper()

    n := strings.Index(s, substr)
    if n != nExpected {
      t.Fatalf("unexpected n; got %d; want %d", n, nExpected)
    }
  }

  // Notice: test description along with t.Helper is a nice combo

  // first chars match
  f("foobar", "foo", 0)

  // middle chars match
  f("foobar", "bar", 3)

  // no match
  f("foobar", "baz", -1)
}
- f() doesn’t accept t *testing.T arg (it can use the arg from the outer test function)
- The first line inside f() is [t.Helper()](https://pkg.go.dev/testing#T.Helper) call
- t.Helper prints the line with the corresponding f() call when some test fails
- So you do not need to name your test scenarios
- Instead you can use code comments with full explanation & context

go install: godotenv

# Derive GOBIN & set it as PATH
GOPATH=$(go env GOPATH)
GOBIN="${GOPATH}/bin"
export PATH="${PATH}:${GOBIN}"

# Install godotenv to read .env file(s)
go install github.com/joho/godotenv/cmd/godotenv@latest

godotenv -h

api in pairs: main && test apis: action, state, specs: bulk specs

  • golang module: relm
  • golang package: relm/pkg/carvel
  • golang file: relm/pkg/carvel/bundle.go
  • last updated date: 23/JUL/2024
package carvel

type AnySpecsValidate interface {
  // public; external clients can invoke
  ValidateSpecs() error
}

type AnyBundlePush interface {
  // AnySpecsValidate ensures the instance of AnyBundlePush can be validated
  AnySpecsValidate

  // private; avoid custom implementations by external client
  pushBundle() (BundleResult, error)
}
type AnyBundlePushAssert interface {
  AnyBundlePush

  assertBundlePush() (AssertResult, error)
}
var _ AnyBundleCreate = &NestedBundleCreateSpecs{}
var _ AnyBundlePush = &BundlePushSpecs{}
var _ AnyPackageCRResolve = &PackageCRResolveSpecs{}
var _ AnyFileCopy = &FileCopySpecs{}
// Copy Package Metadata CR yaml to output location
var myFile1 = FileCopySpecs {
  Source: "path/to/component/package-meta-cr.yaml",
  Destination: "nested/bundle/config/component-v1.0.0/package-meta-cr.yaml",
}
// Resolve Package CR yaml & copy the resolved yaml to output location
var myPkgCR2 = PackageCRResolveSpecs {
  Method: YttFileOut, // Low level operation; declarative
  Source: "path/to/component/package.yaml",
  Destination: "nested/bundle/config/component/package.yaml", 
  KeyValues: map[string]string {
    "version": "v1.0.0",
    "image": "address/component_bundle@sha256:digestxxxx",
  },
}
// Push a bundle file (that was created earlier) to registry, 
// Then resolve the corresponding Package CR yaml using above registry endpoint, 
// Finally copy the resolved Package CR yaml to declared output location
var myBundle1 = &BundlePushSpecs {
  Method: ImgpkgCopyTarToRepo, // Low level operation; declarative
  Source: BundleSourceSpecs {
    BundleFilePath: "${GOBUILD_RELM_PATH}/bundle.tar.gz",
  },
  Destination: BundleDestinationSpecs {
    Address: "localhost:5000",
    BundlePath: "bundles/relm_bun",
    BundleTag: "v1.0.0",    
  },
  PackageCR: &PackageCRResolveSpecs { // [optional];
    Method: YttFileOut,
    Source: "relm/package.yaml", // templated file
    Destination: "nested/bundle/config/relm/package.yaml", 
    KeyValues: map[string]string {
      "version": "v1.0.0",
      "image": "localhost:5000/bundles/relm_bun:v1.0.0",
    },
    KeyValueRefs: map[string]string { // Alternative to KeyValues
      "version": LookupBundleTag,
      "image": LookupBundleURLTag,
    },
    refValues: map[string]string { // Private/Internal; filled up by BundleSpecs
      LookupBundleTag: "v1.0.0",
      LookupBundleURLTag: "localhost:5000/bundles/relm_bun:v1.0.0",
      LookupBundleURLDigest: "localhost:5000/bundles/relm_bun@sha256:digestxxx",
    },
  },
}
  • Summary
- One interface per action i.e. API
- Interfaces determine the main behaviour i.e. API
- Use prefix `Any` for interface names
- Use suffix `Specs` for struct names
- One struct (i.e. specs) for multiple interfaces wherever possible
- Every API should have corresponding Assert API
- Read (i.e. Maintainability) over Write (i.e. Implementation)
  - Distinct, Non ambiguous, Easy to understand
- Use verbose field names in Specs struct
- Use verbose method / function names
  - E.g.: getXXX, runXXX, createXXX, newXXX, etc.
- Keywords:
  - `XXXState` # PackageCRState, etc.; Multiple States per Action
  - `PostOperation` # PreOperation, etc.
  - `Method` # ImgpkgCopy, Ytt, CranePull, etc.
    - Names the `Low Level Operations`
  - `Target` # w.r.t Assert i.e. TargetUnderTest

go example: sdk: api: declarative specs: 1

Introduction

  • go module path: myproject/go.mod
  • go module name: myproj.com
  • go package name: myproject/pkg/carvelgen
package carvelgen

/*
    APIs
 */

// PackageBundle generates a package bundle
func PackageBundle(specs AnyPackageBundle) (PackageBundleResult, error)

// PackageBundles is a bulk operation to generate one or more package bundles
func PackageBundles(specs []AnyPackageBundle) (PackageBundleResultList, error)

// PackageCR generates a Package CR yaml
func PackageCR(specs AnyPackageCR) (PackageCRResult, error)

// PackageMetadataCR generates a PackageMetadata CR yaml
func PackageMetadataCR(specs AnyPackageMetadataCR) (PackageMetadataCRResult, error)

// NestedBundle is same as PackageBundle. However, it has its own signature
// such that it can be extended without impacting PackageBundle
func NestedBundle(specs AnyNestedBundle) (NestedBundleResult, error)

/*
    Contracts

var _ AnyPackageBundle = PackageBundleGobuildDepSpecs{} // pre-built package
var _ AnyPackageBundle = PackageBundleRemotePackageCRSpecs{} // pre-built package
var _ AnyPackageBundle = PackageBundleSpecs{} // pre-built package; available locally
var _ AnyPackageBundle = PackageBundleBuildsquidSpecs{} // pre-built package
var _ AnyPackageBundle = PackageBundlePackageCRSpecs{} // pre-built package
var _ AnyPackageBundle = PackageBundleBuildSpecs{} // build the package

type Compatibility interface {
  isDeprecated() bool
  deprecationMessage() string
}

type AnyPackageBundle interface {
  Compatibility
  isPackageBundleSpecs() bool
  packageBundle() (PackageBundleResult, error)
}

 */

type AnyPackageBundle interface {}
type AnyPackageCR interface {}
type AnyPackageMetadataCR interface {}
type AnyNestedBundle interface {}

type AnyBundleConfig interface {} // e.g. &YttSpecs{}
type AnyImageLock interface {} // e.g. ImageLockKbldSpecs{}

// AnyOperation can define a CLI execution i.e. fire & forget
type AnyOperation interface {} // e.g. &PackageCRCopySpecs{}, &PackageBundleCopySpecs{}

/*
    Outputs
 */

type PackageBundleResult struct {}
type PackageBundleResultList struct {}
type PackageCRResult struct {}
type PackageMetadataCRResult struct {}
type NestedBundleResult struct {}
type OperationResult struct {}

type PackageBundleError struct {}
type PackageCRError struct {}
type PackageMetadataCRError struct {}
type NestedBundleError struct {}
type OperationError struct {}

/*
    Specs
 */

type PackageBundleGobuildDepSpecs struct {
  GobuildDepName string
}

type PackageBundleRemotePackageCRSpecs struct {
  URL string
}

type NestedBundleBuildSpecs struct {
  PackageBundleBuildSpecs
}

type PackageBundleBuildSpecs struct {
  OCIRegistryURL string
  BundleName string
  BundleTag string
  BundleContents BundleContentsSpecs
  Output AnyOperation // output as a .tar.gz & place it a declared file path
  PreBuild PackageBundlePreBuildSpecs // [optional]; e.g. use this to start the OCI registry
  PostBuild PackageBundlePostBuildSpecs // [optional];e.g. use this to resolve Package CR
  Debug bool // [optional];useful during debugging/ troubleshooting
  DryRun bool // [optional]; useful to try at production; without impacting production 

  internalSpecs PackageBundleBuildSpecsInternal // private; values are set internally
}

type PackageBundleBuildSpecsInternal struct {
  SchemaVersion string // version of the specifications
  WorkingDir string // some tmp directory; will be used to run file operations
}

type PackageBundlePreBuildSpecs struct { // name format: <Entity><Action>Specs
  Operations []AnyOperation // e.g. &RegistryStartSpecs{...}
}

type PackageBundlePostBuildSpecs struct { // name format: <Entity><Action>Specs
  Operations []AnyOperation // e.g. &PackageCRResolveSpecs{...}, &PackageCRCopySpecs{...}
}

type BundleContentsSpecs struct { // name format: <Entity>Specs
  BundlePath string
  BundleConfigPath string // [optional]; can be derived from BundlePath
  BundleDotImgpkgPath string // [optional]; can be derived from BundlePath
  ExtraBundleConfigs []AnyBundleConfig // [optional]
  ImageLock AnyImageLock
}

type YttSpecs struct { // name format: <Entity>Specs
  Files []string
  Values map[string]string
  OutputFiles string
}

type ImageLockKbldSpecs struct { // name format: <Entity><SubEntity>Specs
  Files []string
  Output string
}

experiment: edit go.mod using rsc's script

  • Refer: https://github.com/rsc/script/tree/main
  • Goal: Update the declared modules to their local relative paths
  • Goal: Update the declared local module paths to their latest or main commits
  • Goal: Verify presence of any local module paths & error if present
  • Task: hack/gomod_local_set.txt will have business logic / specifications
  • Task: hack/gomod_local_unset.txt will have business logic / specifications
  • Task: hack/gomod_local_err.txt will have business logic / specifications
  • Future: Add this to Github actions
  • Future: Implement this in pure go & provide observations on which one suits when
    • E.g.: which one is applicable to be executed as GitHub actions
    • E.g: How does environments vary in terms of build & runtime dependencies

go mod: retract

module github.com/caarlos0/env/v11

retract v11.0.1 // v11.0.1 accidentally introduced a breaking change regarding the behavior of nil pointers. You can now chose to auto-initialize them by setting the `init` tag option.

go 1.18

go: slice: string: byte: unsafe: error: unwrap

  • refer: go standard errors package
// Join returns an error that wraps the given errors.
// Any nil error values are discarded.
// Join returns nil if every value in errs is nil.
// The error formats as the concatenation of the strings obtained
// by calling the Error method of each element of errs, with a newline
// between each string.
//
// A non-nil error returned by Join implements the Unwrap() []error method.
func Join(errs ...error) error {
    n := 0
    for _, err := range errs {
        if err != nil {
            n++
        }
    }
    if n == 0 {
        return nil
    }
    e := &joinError{
        errs: make([]error, 0, n),
    }
    for _, err := range errs {
        if err != nil {
            e.errs = append(e.errs, err)
        }
    }
    return e
}

type joinError struct {
    errs []error
}
func (e *joinError) Error() string {
    // Since Join returns nil if every value in errs is nil, e.errs cannot be empty.
    if len(e.errs) == 1 {
        return e.errs[0].Error()
    }
    
    b := []byte(e.errs[0].Error()) // amit: initialize
    for _, err := range e.errs[1:] {
        b = append(b, '\n') // amit: the char i.e. '\n' helps separate the error list when the list is logged
        b = append(b, err.Error()...) // amit: notice how string is used as list of chars
    }
    // At this point, b has at least one byte '\n'. // amit: correct
    return unsafe.String(&b[0], len(b)) // amit: start from address of b to its whole length
}
func (e *joinError) Unwrap() []error {
    return e.errs
}

go: flag: cli

func usage() {
    fmt.Fprintf(os.Stderr, "usage: gonew srcmod[@version] [dstmod [dir]]\n")
    fmt.Fprintf(os.Stderr, "See https://pkg.go.dev/golang.org/x/tools/cmd/gonew.\n")
    os.Exit(2)
}

func main() {
    log.SetPrefix("gonew: ")
    log.SetFlags(0)
    flag.Usage = usage
    flag.Parse()
    args := flag.Args()
    
    if len(args) < 1 || len(args) > 3 {
    usage()
    }
    
    // more code ...
}

experience: scripting vs programming - 1

  • Given: Most of your day job is around file handling, packaging, etc.
  • Given: Alternatively, you work in build & release operations
  • Then: Scripting seems to be a natural choice with its terse logic, &
    • the plethora of CLIs available to further reduce the lines of logic
  • Fact: File operations & unix philosophy goes hand-in-hand
  • However: Addition of business requirements makes scripting a bad choice
  • E.g.: I want to dry run the logic in production systems
  • E.g.: I run the logic in mission critical environments
    • Like hospitals, meteorology, transport, telecom, industrial automation, etc.
    • Or even your startup where you do not want to lose a customer for a syntactical error
  • E.g.: I want to run the logic in different OSes & architectures
  • E.g.: I want to bank on multiple release versions due to complex maintenance windows
  • E.g.: I want to run your tests in my systems (i.e. enduser platforms, etc.)
  • Then: We must switch to programming languages that are designed to be safe
  • E.g.: Above translates to following technical requirements:
    • Compile time checks,
    • Idempotent operations,
    • Supply chain security,
    • Build reproducibility,
    • Forward & backward compatibility,
    • Testing, etc.
  • And: Above translates into several non technical requirements like:
    • Investing in teams, plans / sprints, designs, etc.
  • Summary: Ensure correct logic instead of writing logic in few lines of code
  • Summary: Simple logic (or less lines of code) is relative
  • Summary: Instead focus on production grade logic

go enum: sample

// refer: https://github.com/golang/go/issues/64739
type country struct{string} 
type Country struct{}
func(c Country) Australia() country {...} 
func(c Country) Canada() country {...}
func(c Country) China() country {...}
func(c Country) England() country {...}
func(c Country) France() country {...}
func(c Country) Germany() country {...}
func(c Country) Japan() country {...}
func(c Country) Mexico() country {...}
func(c Country) Morocco() country {...}
func(c Country) Zimbabwe() country {...}
// ... 

go: dotenv: scaffolding: bootstrap: setup

  • https://github.com/joho/godotenv
  • use_case: setup env & folder structure as part of project setup
  • idea:
    • define spec fields that is generated into a .env file
    • define spec fields that is generated into required folders
    • tip: make use of godotenv to generate .env file
    • tip: make use of go standard packages to generate folders

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.