Create function that require other repeatbale logic as pre-requiste (clean code)

clean code small functions
clean code function length
clean code java
clean code books
clean code kindle

I've the following yaml file which I need to parse (the parse is working as expected) and need to provide a datafrom the yaml file content that should be exposed by the following decoupled functions

I need to provide the following functions (here is example of some of those functions, need more with the same pattern...)

getApps()

getServices()

GetApp(appname)

GetServiceForApp(appname)

This is the code (which works...)

var DMZ = []byte(`
applications:
  - name: app1
    type: php
    src: /app1
    host: us
    use: 
      - redis
      - mysql

  - name: app2
    type: rust
    src: /app2
    host: eu
    use: 
      - mongo
      - mysql

  - name: app3
    type: golang
    src: /app3
    host: us
    use: 
      - postgress
      - mysql


services:
  - name: mongo
    type: db
    host: us

  - name: mysql
    type: db
    host: eu

  - name: postgress
    type: db
    host: us

  - name: redis
    type: db
    host: us   
`)

This is the structs

type DMZ struct {
  Applications       []*Applications   `yaml:"applications,omitempty"`
  Services           []*Services       `yaml:"services,omitempty"`
}

type Applications struct {
  Name        string
  Type        string
  Src        string            `yaml:"src,omitempty"`
  use        []Use             `yaml:"use,omitempty"`
}
type Services struct {
  Name        string
  Type        string
  Host        string            `yaml:"host,omitempty"`
}
type Use struct {
  Name       string     `yaml:"name,omitempty"`
  host       string     `yaml:"host,omitempty"`
  Type       string     `yaml:"type,omitempty"`
}



// Parse file
func Parse(yamlContent []byte) (out DMZ, err error) {
  dmz := DMZ{}
  err = yaml.Unmarshal([]byte(yamlContent), &dmz)
  if err != nil {
    logs.Error("Yaml file is not valid, Error: " + err.Error())
  }
  return dmz, err
}

As the Parse function is a per-requite to all the needed functions (which I listed above) I wonder how is the best to create them ,create simple function that every time call to the parse function and then do the logic (not a problem) but I wonder if there is better approach which follows the clean code principles for Golang , with 'interface / dependency injections' ?

UPDATE:

I want to avoid doing things like following, assume that I need to call to those function from different packages or even different GitHub repository how it's best to do it with Golang clean code.

func getApps(){

 dmz := Parse()
....
}


func getServices(){

 dmz := Parse()
....

}


func getApp(appname string){

 dmz := Parse()
....

}


func GetServiceForApp(appname string){

 dmz := Parse()
....

}

And I need more functions with the same pattern ...

What I need some Clean Code solution using interface/dependency injection like a best practice code example in Golang

If something is not clear please let me know :)


Parse the value inside pointer type struct value which will store the value inside the struct pointed by a pointer. Then Create method receives on All the methods from which you want to get the value of an app or service inside the struct.

Using pointer receiver in all methods you will be able to access the original struct which is updated when parsing the yaml.

Create a pointer to empty instance of the struct and pass it as a method receiver. Then access that struct in unmarshal to update yaml data in original struct. Access the updated struct in every function by accessing the value of original struct using pointer receiver to method.

package main

import (
    "fmt"
    "log"

    yaml "gopkg.in/yaml.v2"
)

var dmz = []byte(`
applications:
  - name: app1
    type: php
    src: /app1
    host: us
    use: 
      - redis
      - mysql

  - name: app2
    type: rust
    src: /app2
    host: eu
    use: 
      - mongo
      - mysql

  - name: app3
    type: golang
    src: /app3
    host: us
    use: 
      - postgress
      - mysql


services:
  - name: mongo
    type: db
    host: us

  - name: mysql
    type: db
    host: eu

  - name: postgress
    type: db
    host: us

  - name: redis
    type: db
    host: us   
`)

type DMZ struct {
    Applications []*Applications `yaml:"applications,omitempty"`
    Services     []*Services     `yaml:"services,omitempty"`
}

type Applications struct {
    Name string
    Type string
    Src  string `yaml:"src,omitempty"`
    use  []Use  `yaml:"use,omitempty"`
}
type Services struct {
    Name string
    Type string
    Host string `yaml:"host,omitempty"`
}
type Use struct {
    Name string `yaml:"name,omitempty"`
    host string `yaml:"host,omitempty"`
    Type string `yaml:"type,omitempty"`
}

func main() {
    dm := &DMZ{}
    result, err := dm.Parse(dmz)
    dm.getApp("app1")
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(result)
    fmt.Println(dm.getApp("app2"))
    fmt.Println(dm.GetServiceForApp("mongo"))
}

func (dmz *DMZ) getApps() []*Applications {
    return dmz.Applications
}

func (dmz *DMZ) getServices() []*Services {
    return dmz.Services
}

func (dmz *DMZ) getApp(appname string) *Applications {
    for _, value := range dmz.Applications {
        if appname == value.Name {
            fmt.Println((*value).Name)
            return value
        }
    }
    return nil
}

func (dmz *DMZ) GetServiceForApp(appname string) *Services {
    for _, value := range dmz.Services {
        if appname == value.Name {
            return value
        }
    }
    return nil
}

// Parse file
func (dmz *DMZ) Parse(yamlContent []byte) (out *DMZ, err error) {
    err = yaml.Unmarshal([]byte(yamlContent), &dmz)
    if err != nil {
        log.Fatal("Yaml file is not valid, Error: " + err.Error())
    }
    return dmz, err
}

Working code on Playground

If you want your code to be more clean then you can also skip the struct returned from parse function. Since we are passing a pointer type receiver and updating the original struct as:

package main

import (
    "fmt"
    "log"

    yaml "gopkg.in/yaml.v2"
)

var dmz = []byte(`
applications:
  - name: app1
    type: php
    src: /app1
    host: us
    use: 
      - redis
      - mysql

  - name: app2
    type: rust
    src: /app2
    host: eu
    use: 
      - mongo
      - mysql

  - name: app3
    type: golang
    src: /app3
    host: us
    use: 
      - postgress
      - mysql


services:
  - name: mongo
    type: db
    host: us

  - name: mysql
    type: db
    host: eu

  - name: postgress
    type: db
    host: us

  - name: redis
    type: db
    host: us   
`)

type DMZ struct {
    Applications []*Applications `yaml:"applications,omitempty"`
    Services     []*Services     `yaml:"services,omitempty"`
}

type Applications struct {
    Name string
    Type string
    Src  string `yaml:"src,omitempty"`
    use  []Use  `yaml:"use,omitempty"`
}
type Services struct {
    Name string
    Type string
    Host string `yaml:"host,omitempty"`
}
type Use struct {
    Name string `yaml:"name,omitempty"`
    host string `yaml:"host,omitempty"`
    Type string `yaml:"type,omitempty"`
}

func main() {
    dm := &DMZ{}
    dm.Parse(dmz)
    fmt.Println(dm.getApp("app2"))
    fmt.Println(dm.GetServiceForApp("mongo"))
}

func (dmz *DMZ) getApps() []*Applications {
    return dmz.Applications
}

func (dmz *DMZ) getServices() []*Services {
    return dmz.Services
}

func (dmz *DMZ) getApp(appname string) *Applications {
    for _, value := range dmz.Applications {
        if appname == value.Name {
            fmt.Println((*value).Name)
            return value
        }
    }
    return nil
}

func (dmz *DMZ) GetServiceForApp(appname string) *Services {
    for _, value := range dmz.Services {
        if appname == value.Name {
            return value
        }
    }
    return nil
}

// Parse file
func (dmz *DMZ) Parse(yamlContent []byte) {
    if err := yaml.Unmarshal([]byte(yamlContent), &dmz); err != nil {
        log.Fatal("Yaml file is not valid, Error: " + err.Error())
    }
}

As we can notice that Parse function will become more clean since we are not returning anything from it we are just updating the original struct using method receiver which is a much better way to achieve what you have been trying to achieve.

You can also choose to implement an interface by defining the methods in struct as receiver for which you are trying to implement the interface as:

package main

import (
    "fmt"
    "log"

    yaml "gopkg.in/yaml.v2"
)

type DI interface {
    GetApps() []*Applications
    GetServices() *Services
}

var dmz = []byte(`
applications:
  - name: app1
    type: php
    src: /app1
    host: us
    use: 
      - redis
      - mysql

  - name: app2
    type: rust
    src: /app2
    host: eu
    use: 
      - mongo
      - mysql

  - name: app3
    type: golang
    src: /app3
    host: us
    use: 
      - postgress
      - mysql


services:
  - name: mongo
    type: db
    host: us

  - name: mysql
    type: db
    host: eu

  - name: postgress
    type: db
    host: us

  - name: redis
    type: db
    host: us   
`)

type DMZ struct {
    Applications []*Applications `yaml:"applications,omitempty"`
    Services     []*Services     `yaml:"services,omitempty"`
}

type Applications struct {
    Name string
    Type string
    Src  string `yaml:"src,omitempty"`
    use  []Use  `yaml:"use,omitempty"`
}
type Services struct {
    Name string
    Type string
    Host string `yaml:"host,omitempty"`
}
type Use struct {
    Name string `yaml:"name,omitempty"`
    host string `yaml:"host,omitempty"`
    Type string `yaml:"type,omitempty"`
}

func main() {
    dm := &DMZ{}
    dm.Parse(dmz)
    fmt.Println(dm.getApp("app2"))
    fmt.Println(dm.GetServiceForApp("mongo"))
}

func (dmz *DMZ) GetApps() []*Applications {
    return dmz.Applications
}

func (dmz *DMZ) GetServices() []*Services {
    return dmz.Services
}

func (dmz *DMZ) getApp(appname string) *Applications {
    for _, value := range dmz.Applications {
        if appname == value.Name {
            fmt.Println((*value).Name)
            return value
        }
    }
    return nil
}

func (dmz *DMZ) GetServiceForApp(appname string) *Services {
    for _, value := range dmz.Services {
        if appname == value.Name {
            return value
        }
    }
    return nil
}

// Parse file
func (dmz *DMZ) Parse(yamlContent []byte) {
    if err := yaml.Unmarshal([]byte(yamlContent), &dmz); err != nil {
        log.Fatal("Yaml file is not valid, Error: " + err.Error())
    }
}

Note:

Generics are convenient but they come at a cost in complexity in the type system and run-time. We haven't yet found a design that gives value proportionate to the complexity, although we continue to think about it. Meanwhile, Go's built-in maps and slices, plus the ability to use the empty interface to construct containers (with explicit unboxing) mean in many cases it is possible to write code that does what generics would enable, if less smoothly.

Small Functions considered Harmful - Cindy Sridharan, The book Clean Code — often considered something of a There's too much going on in there at too many different levels of abstraction. small functions that the idea of abstracting any and every piece of logic that might Additionally, creating a user might also require sending them a welcome email. A function is an instruction carried out within a program. The instruction can include arguments or require certain inputs to run successfully. Functions are typically arranged in a certain order to achieve a desired result.


You can define an interface and provide implementations in the struct

type DMZI interface {
    GetApps() []Application
    GetService() []Service
    GetApp(name string) (Application, error)
    GetServiceForApp(name string) ([]string, error)
}

type DMZ struct {
    Application []Application `yaml:"applications,omitempty"`
    Service     []Service     `yaml:"services,omitempty"`
}

func (dmz DMZ) GetApps() []Application {
    return dmz.Application
}

func (dmz DMZ) GetService() []Service {
    return dmz.Service
}

func (dmz DMZ) GetApp(name string) (Application, error) {
    for _, app := range dmz.Application {
        if app.Name == name {
            return app, nil
        }
    }
    return Application{}, fmt.Errorf("Did not find application with name %s", name)
}

func (dmz DMZ) GetServiceForApp(name string) ([]string, error) {
    app, err := dmz.GetApp(name)
    if err != nil {
        return []string{}, err
    }
    return app.Use, nil
}

type Application struct {
    Name string
    Type string
    Src  string   `yaml:"src,omitempty"`
    Use  []string `yaml:"use,omitempty"`
}
type Service struct {
    Name string
    Type string
    Host string `yaml:"host,omitempty"`
}

// Parse file
func Parse(yamlContent []byte) (out DMZI, err error) {
    dmz := DMZ{}
    err = yaml.Unmarshal([]byte(yamlContent), &dmz)
    if err != nil {
        fmt.Println("Yaml file is not valid, Error: " + err.Error())
    }
    return dmz, err
}

So, you can call the methods on the returned interface e.g.

fmt.Printf("Apps : %+v\n", dmz.GetApps())
fmt.Printf("Service : %+v\n", dmz.GetService())

UPDATE

main method as requested in the comment

func main() {
    dmz, err := Parse([]byte(ymlStr))
    if err != nil {
        panic(err)
    }
    fmt.Printf("Apps : %+v\n", dmz.GetApps())
    fmt.Printf("Service : %+v\n", dmz.GetService())
}

Will print

Apps : [{Name:app1 Type:php Src:/app1 Use:[redis mysql]} {Name:app2 Type:rust Src:/app2 Use:[mongo mysql]} {Name:app3 Type:golang Src:/app3 Use:[postgress mysql]}]
Service : [{Name:mongo Type:db Host:us} {Name:mysql Type:db Host:eu} {Name:postgress Type:db Host:us} {Name:redis Type:db Host:us}]

Is it always a best practice to write a function for anything that needs , It often makes sense to create a function for something that's only executed once. Most programmers tend to err too far the other way. If I need to do something once I'll write that code, twice I may just copy / paste (yes I just However, in Python it is fairly light-weight to reuse, rather than repeat, logic. The Allowable Repeats process, which enables you to define rules on the Catalog Data page of the Course Catalog (CRSE_CATALOG) component that regulate whether a student can repeat a course or course topic for credit and, if so, how many total units and total completions the student can attempt. In


I've changed your code a little and done what I think you are asking for, which is to always call "Parse" whenever you create a new instance of DMZ. This is how you would do this using Dargo. Look at the bottom to see how the code would bind DMZ into a ServiceLocator and how to get new instances of DMZ

type DMZ struct {
    Applications []*Applications `yaml:"applications,omitempty"`
    Services     []*Services     `yaml:"services,omitempty"`
}

// This method is called every time DMZ is created via the Dargo API
func (dmz *DMZ) DargoInitialize(ioc.Descriptor) error {
    // get ur bytes from... wherever
    Parse(dmz, []byte{})
}

type Applications struct {
    Name string
    Type string
    Src  string `yaml:"src,omitempty"`
    use  []Use  `yaml:"use,omitempty"`
}
type Services struct {
    Name string
    Type string
    Host string `yaml:"host,omitempty"`
}
type Use struct {
    Name string `yaml:"name,omitempty"`
    host string `yaml:"host,omitempty"`
    Type string `yaml:"type,omitempty"`
}

// Parse file
func Parse(dmz *DMZ, yamlContent []byte) (out *DMZ, err error) {
    err = yaml.Unmarshal([]byte(yamlContent), &dmz)
    if err != nil {
        logs.Error("Yaml file is not valid, Error: " + err.Error())
    }
    return dmz, err
}

func useDargo() error {
    locator, err := ioc.CreateAndBind("example", func(binder ioc.Binder) error {
        binder.Bind("DMZ", &DMZ{}).InScope(ioc.PerLookup)
    })
    if err != nil {
        return err
    }

    // This is how you would get your instances of DMZ
    locator.GetDService("DMZ")
}

How do you justify more code being written by following clean code , Where you get into trouble is when you create a isEmailValid method which has side For application B, the developer changes the (unique, shared) logic Yes​, in the short term, clean code requires more effort now, but it will end You add a slight complexity burden to all other functions where this new  Node modules have a one-to-one relation with files on the file-system. We require a module by loading the content of a file into memory. However, since Node allows many ways to require a file (for example, with a relative path or a pre-configured path), before we can load the content of a file into the memory we need to find the absolute


Goodbye, Clean Code, I encourage my devs to follow a rule of thumb: don't extract repetitive code right Maybe 3 is for those who need to move fast and break things though. We're talking about extracting a short function, not significant and potentially thorny the one hand you create abstraction and centralizing code logic at the cost of, first​,  WordPress now offers a function, get_template_part(), that is part of the native API and is used specifically for reusing sections - or templates - of code (except for the header, footer, and sidebar) through your theme. The function accepts two arguments: The first argument is the slug for the template. In the example above, that would be 'loop'.


These four “clean code” tips will dramatically improve your , Writing new features and even minor bug fixes required a… A few years ago at VideoBlocks we had a major code quality problem: “spaghetti” logic in most files, tons Out of all the ideas we implemented from Clean Code and other Functions should be no more than 4 lines and classes no more than  In contrast, an Azure Function requires you to run configuration on each and every use. If you look at many of the code examples for Azure Functions, you tend to see often those examples repeating boilerplate code for things like configuration. Looking at an Azure Function in isolation, this probably doesn't appear to be much of an issue.


Grade 1 Red, Grade 1 Red Principles Don't Repeat Yourself (DRY) Why? They recognize repetitions created by themselves or others. Prerequisite for evolvability of code is that code is comprehensible. By reducing the absolutely required into the shortest possible form it may fulfill the customer's functional and non-​functional  the set of curly braces that contains the function statements in a function definition Function call the code that calls a function, which consists of the function name followed by parentheses, which contain any arguments to be passed to the function.