728x90
반응형

  구글 엔지니어 하이럼이 이야기 하는 법칙

https://www.hyrumslaw.com/

 

Hyrum's Law

Hyrum's Law An observation on Software Engineering Put succinctly, the observation is this: With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by som

www.hyrumslaw.com

소프트웨어 엔지니어링의 관찰

API 사용자가 충분 하면 명세서에 약속된 내용이 중요하지 않습니다.
시스템에서 관찰할 수 있는 모든 동작은 누군가에 의해 좌우됩니다.

지난 몇 년 동안 지구상에서 가장 복잡한 소프트웨어 시스템 중 하나에서 저수준 인프라 마이그레이션을 수행하면서 인터페이스와 구현 간의 차이점에 대해 몇 가지 관찰했습니다. 우리는 일반적으로 인터페이스를 시스템과 상호 작용하기 위한 추상화(예: 자동차의 스티어링 휠 및 페달)로 생각하고 구현은 시스템이 작동하는 방식(바퀴 및 엔진)으로 생각합니다. 이것은 여러 가지 이유로 유용합니다. 그 중 가장 중요한 이유는 가장 유용한 시스템이 한 개인이나 그룹이 완전히 이해하기에는 너무 복잡해지며 추상화는 그 복잡성을 관리하는 데 필수적입니다.

정확한 추상화 수준을 정의하는 것은 완전히 별개의 논의이지만(Mythical Man-Month 참조), 우리는 추상화가 정의되면 구체적이라고 생각하는 것을 좋아합니다. 다시 말해, 인터페이스는 이론적으로 시스템 소비자와 구현자를 명확하게 구분해야 합니다. 실제로, 이 이론은 시스템의 사용이 증가하고 사용자가 인터페이스를 통해 의도적으로 노출되거나 정기적인 사용을 통해 확인하는 구현 세부 사항에 의존하기 시작하면서 무너집니다. Spolsky의 "Leaky Abstractions의 법칙"은 내부 구현 세부 사항에 대한 소비자의 의존성을 구현합니다.

논리적으로 극단으로 치면 구어체로 "암시적 인터페이스의 법칙"이라고 하는 다음과 같은 관찰 결과가 나타납니다. 충분히 사용하면 비공개 구현과 같은 것은 없습니다. 즉, 인터페이스에 충분한 소비자가 있으면 의도적이든 아니든 구현의 모든 측면에 집합적으로 의존하게 됩니다. 이 효과는 구현에 대한 변경을 제한하는 역할을 합니다. 이제 명시적으로 문서화된 인터페이스와 사용에 의해 캡처된 암시적 인터페이스를 모두 준수해야 합니다. 우리는 종종 이 현상을 "버그 대 버그 호환성"이라고 합니다.

암시적 인터페이스의 생성은 일반적으로 점진적으로 이루어지며 인터페이스 소비자는 일반적으로 이러한 일이 진행되는 동안 인식하지 못합니다. 예를 들어, 인터페이스는 성능에 대해 보장하지 않을 수 있지만 소비자는 종종 구현에서 특정 수준의 성능을 기대하게 됩니다. 이러한 기대는 시스템에 대한 암시적 인터페이스의 일부가 되며 시스템의 변경 사항은 소비자를 위해 계속 기능하기 위해 이러한 성능 특성을 유지해야 합니다.

모든 소비자가 동일한 암시적 인터페이스에 의존하는 것은 아니지만 충분한 소비자가 주어지면 암시적 인터페이스는 결국 구현과 정확히 일치합니다. 이 시점에서 인터페이스는 증발했습니다. 구현이 인터페이스가 되었으며, 인터페이스에 대한 변경 사항은 소비자의 기대를 위반하게 됩니다. 운이 좋으면 광범위하고 포괄적이며 자동화된 테스트를 통해 이러한 새로운 기대치를 감지할 수 있지만 개선할 수는 없습니다.

암시적 인터페이스는 대규모 시스템의 유기적 성장으로 인해 발생하며 문제가 존재하지 않기를 바랄 수도 있지만 설계자와 엔지니어는 복잡한 시스템을 구축 및 유지 관리할 때 이를 고려하는 것이 현명합니다. 따라서 암시적 인터페이스가 시스템 설계와 발전을 어떻게 제한하는지 알고, 합리적으로 널리 사용되는 시스템의 경우 인터페이스가 생각보다 훨씬 더 깊숙이 도달한다는 것을 알고 있습니다.

728x90
반응형
728x90
반응형
728x90
반응형

'개발 일반' 카테고리의 다른 글

하이럼의 법칙  (0) 2022.11.12
GO 언어 기본 정리  (0) 2022.02.20
Go 웹서버 만들기  (0) 2022.02.02
Python 오늘 날짜 구하기, 날짜 사이 간격 구하기  (0) 2020.04.06
PyCharm 가상 개발 환경 windows to Linux  (0) 2020.03.22
728x90
반응형

함수

함수는 함수정의 키워드, 함수명, 매개변수, 반환타입의 4가지로 이루어진다

func Attach(data string) string {
     <본문> 
     return result
}

위의 첫째줄을 순서대로 해석하면 아래와 같다.
func : 함수임을 나타낸다
Attach : 함수명
data : 매개변수명
string : 매개변수 타입
string : 반환 타입

리턴은 두가지를 다중 반환 하도록 다중 반환함수를 만들수도 있다.
func Attach(data string) (string, int) 

위와 같은 경우에는 아래처럼 사용하면 된다.
ret, index := Attach(data)

분기문

 

if 문

if 조건문 { 코드 
}else if 조건문 { 코드
} else { 코드
}

예제

if data == "hello" {
fmt.Println("hello") 
} else if data == "bye" {
 fmt.Println("bye")
} else {
 fmt.Println("Good bye")
}

if의 조건문은 && , ||을 이용하여 구성하여 사용한다.
여러개의 조건문을 활용할 경우 괄호를 이용하여 묵어야 한다. 

if문에 초기문과 조건문을 같이 넣기
if rets := tf(true); rets {
if rets := tf(true); rets == true {

위의 문장은 tf 함수에 매개변수로 true를 넣고 함수를 실행한 이후 결과가 true일 때에 if문을 참으로 인식하고 동작하는 초기분을 넣었다. 초기문은 ";" 를 이용하여 넣고 뒷 부분에 매개변수를 통한 조건문이나 조건문을 넣을수 있다.

switch문

switch문은 값에 따라서 수행해야 하는 경우가 틀릴 경우 사용함

    switch data {
    case "hello":
        fmt.Println("hello")
    case "bye":
        fmt.Println("bye")
    default:
        fmt.Println("Good Bye")
    }

다양한 사용법이 존재함
다중 조건 case 사용
 case "hello", "bye":

조건문을 이용한 case 문을 사용
case degree > 5:

초기값을 이용하여 함수를 호출한 이후 사용
    switch rets := tf(false); rets {
    case true:
        fmt.Println("hello")

for문

for문은 조건을 가진 반복 작업에 사용
for 초기화; 조건문; 증가자 {
  <코드>
}

예제
for a := 0; a < 10; a++ {
  fmt.Print(a)

continue와 break를 이용하여 구성 가능함

 

데이터 다루기

배열

배열은 같은 데이터 타입으로 이루어진 값들의 묶음

선언

var 변수명 [사이즈]타입
var data [100]string

초기화 및 데이터 입력

    var data3 [5]string = [5]string{"haha", "hihi", "huhu"}
    초기화 하면서 같은 사이즈의 배열을 할당

    data3[3] = "hoho"
    비어있는 3번에 데이터 입력

출력 방식
    for i, a := range data3 {
        fmt.Println(i, a)
    }

range를 이용하여 들어간 배열 만큼 동작 하다록 함
자바나 타 언어와 동일하게 다중 배열 사용 가능함

구조체

  구조체는 C에서 자주 사용하던 것과 거의 유사하게 사용할 수 있게 된 데이터들의 집합이다. 

선언
type <구조체명> struct {
  필드명  데이터타입
  필드명  데이터타입
}

위와 같이 선언하여 사용 할수 있다.
그럼 실제로 구조체를 선언하여 사용해 보자

type Member  struct {
  UserID string
  UserNo int
  Name string
  Address string
}

func main() {
  var member Member
  member.Address = "부산시...."

    fmt.Println(member.Address)
}

 

만약 구조체 배열 즉 slice를 만든 다음에 해당 구조체에 값을 추가 하고자 할 경우에는 아래와 같다.

 

var member2 []Member
member := Member{"guest", 1213, "김수로", "경기도"}
member2 = append(member2, member)

위에서 정의한 Member가 할당된 member에 값을 할당한 다음 이를 member2 슬라이스에 append 하면 되는 구 조이다. 
 실제로 자바와 유사함

  

참고자료

GO 언어의 표준 패키지 검색

https://golang.org/pkg

 

Standard library - pkg.go.dev

Directories ¶ Expand all tar Package tar implements access to tar archives. Package tar implements access to tar archives. zip Package zip provides support for reading and writing ZIP archives. Package zip provides support for reading and writing ZIP arch

pkg.go.dev

 
 
외부 패키지 검색

https://github.com/avelino/awesome-go

 

GitHub - avelino/awesome-go: A curated list of awesome Go frameworks, libraries and software

A curated list of awesome Go frameworks, libraries and software - GitHub - avelino/awesome-go: A curated list of awesome Go frameworks, libraries and software

github.com

 

go.modGo 1.11부터 go 명령은 디렉토리가 외부 에 있는 경우 현재 디렉토리 또는 상위 디렉토리에 a가 있는 경우 모듈을 사용할 수 있도록 합니다 

728x90
반응형

'개발 일반' 카테고리의 다른 글

하이럼의 법칙  (0) 2022.11.12
Go로 만드는 Slack Bot  (0) 2022.06.04
Go 웹서버 만들기  (0) 2022.02.02
Python 오늘 날짜 구하기, 날짜 사이 간격 구하기  (0) 2020.04.06
PyCharm 가상 개발 환경 windows to Linux  (0) 2020.03.22
728x90
반응형

 

 

% Tucker의 Go 언어 프로그래밍중 발췌

package main

import (
"fmt"
"net/http"
"strconv"
)

func barHandler(w http.ResponseWriter, r *http.Request) {
values := r.URL.Query()  
name := values.Get("name" 
if name == "" {
name = "World"
}
id, _ := strconv.Atoi(values.Get("id")) 
fmt.Fprintf(w, "Hello %s! id:%d", name, id)
}

func main() {
mux := http.NewServeMux()  
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello World" 
})
mux.HandleFunc("/bar", barHandler)
mux.Handle("/static", http.FileServer(http.Dir("static")))  

http.ListenAndServe(":3000", mux)  
}
728x90
반응형
728x90
반응형

 

 

from datetime import datetime

# return : string '2020-03-01'
def gettoday():
    today = datetime.today().strftime("%Y-%m-%d")
    return today

# start_date : string  '2020-03-01'
# end_date : string  '2020-03-04'
# return : int  : 3
def get_datediff(start_date, end_date):
    betday = datetime.strptime(end_date,"%Y-%m-%d").date() - datetime.strptime(start_date,"%Y-%m-%d").date()
    return betday.days


if __name__ == "__main__":
    print(gettoday() )
    betday = get_datediff( '2020-03-01' , gettoday() )
    print( betday )

 

  간단하게 파이선으로 오늘 날짜를 구하고 두개 날짜의 차이를 구하는 함수

  날짜로 배치작업을 돌려야 할때 요긴하게 사용가능해 보인다. 다른 방법도 많지만.. 


#간단한게 가장 좋다.

728x90
반응형
728x90
반응형

  윈도우즈에서 Pycharm을 사용해서 개발을 하는 경우가 종종 있다. PyCharm으로 개발은 하였지만 실제 코드가 동작하는 환경은 리눅스이기 때문에 이를 옮겨 주어야 한다. 

 

  이때 PyCharm의 편리한 기능중 하나인 Python 가상 환경으로 개발을 진행할수 있다.

  다만 이때 윈도우즈에서 가상환경으로 개발을 진행하게 되면 가상 환경의 실행 파일들이 모두 윈도우즈 exe 파일로 설치되게 된다. 이렇게 개발된 가상환경을 바로 유닉스 환경에서는 실행이 되지 않고 당연히 별도의 가상 환경을 해당 유닉스 시스템에 만들어 준 이후에 해주어야 한다. (윈도우즈의 가상 환경을 바로 이동 시킬수 있는 방법이 있는지는 모르겠다.)

 

   이때 해당 파이선 버전의 환경은 가상환경으로 유닉스상에서 만들기 편하지만 라이브러리의 경우에는 모두 이동을 해주어야 한다.

 

  여러가지 의존성들이 설치된 상태

 

  이때 아래의 명령어를 이용해서 간단하게 의존성을 추출하고 설치를 진행 할수 있다.

 

  방법

1. PyCharm 상에서 터미널창을 연 다음 아래의 명령어 수행

 

  > pip freeze > requirements.txt

 

2. requirements.txt 로 위의 버전 정보 추출 확인

 

beautifulsoup4==4.8.1
html5lib==1.0.1
lxml==4.4.2
numpy==1.17.4
pandas==0.25.3
psycopg2==2.8.4
python-dateutil==2.8.1
pytz==2019.3
singleton==0.1.0
six==1.13.0
soupsieve==1.9.5
webencodings==0.5.1

 

3. 유닉스 환경에서 아래의 명령어들을 이용하여 가상 환경 생성

 

> python -m venv env --without-pip

  (--without-pip 옵션은 제거하여도 된다. 에러가 난다면 추가한다.)

> source env/bin/activate

> pip install -r requirements.txt

 

pip가 제대로 설치되지 않아 --without-pip를 설정하였으므로 pip가 설치되지 않은 상태이므로 아래의 명령어로 설치해준다.

> curl https://bootstrap.pypa.io/get-pip.py | python

 

  이제 윈도우에서 개발한 환경 그대로 사용이 가능해 질 것이다.

728x90
반응형
728x90
반응형

전문적으로 Python으로 개발하지 않더라도 Python으로 이것저것 개발하거나 혹은 인터넷이나 Github상에서 다운로드한 소스코드를 동작해야 할 일이 꽤 많을 것이다.  그럴때 아래와 같이 잘 예외 처리가 된 코드를 보았다고 생각해 보자..


    lineList = []

    try:

        f = open(fileName, 'r', encoding='latin-1')


    except IOError:

        print("[!] Could not open file " + fileName)

        exit(1)


    except:

        print("[!] Could not access file " + fileName)

        exit(1)


    for line in f.readlines():

        newLine = line.replace('\n', '')

        lineList.append(newLine)


  단지 파일의 내용을 읽은 다음 단순히 리스트에 하나씩 넣어주는 단순한 코드 이다.

 근대 위의 코드를 실행해 보면 아래와 같이 에러가 난다.



[!] Could not access file ./usernames.txt


예외처리가 되어 있어 아무런 에러 메시지가 나지 않는다. 제일 쉬운 에러 메시지를 보는 방법은 try, except를 모두 제거 해버리면 된다. 그러나 열심히 짜둔 코드를 에러 하나 보겠다고 즉 Stack Trace 하나 하겠다고 지우고 다시 짜기엔 귀차니즘이 용납하지 않는다. 이럴때 에러 로깅을 한가지 넣어서 해결 해 보자.


아래와 같이 코드를 수정한다.


    import traceback

    lineList = []

    try:

        f = open(fileName, 'r', encoding='latin-1')


    except IOError:

        print("[!] Could not open file " + fileName)

        traceback.print_stack()

        traceback.print_exc()

        exit(1)


    except:

        print("[!] Could not access file " + fileName)

        traceback.print_stack()

        traceback.print_exc()

        exit(1)


    for line in f.readlines():

        newLine = line.replace('\n', '')

        lineList.append(newLine)


   위와 같이 변경하고 나면 아래와 같이 encoding이 잘못된 키워드로 함수내에 정의되었다는 에러 메시지를 볼수 있다.


TypeError: 'encoding' is an invalid keyword argument for this function


  위에서 사용한 traceback은 python상에서 위와 같이 예외처리등이 수행된 상태에서 Stack Trace를 출력하기에 상당히 유용한 모듈이다. 상세한 설명은 아래의 링크를 참고하기 바란다.


https://docs.python.org/2/library/traceback.html


This module provides a standard interface to extract, format and print stack traces of Python programs. It exactly mimics the behavior of the Python interpreter when it prints a stack trace. This is useful when you want to print stack traces under program control, such as in a “wrapper” around the interpreter





728x90
반응형

+ Recent posts