document is built now

This commit is contained in:
monoid 2022-04-21 19:23:36 +09:00
parent 0d9b376bb9
commit fc11b930d4
10 changed files with 62 additions and 606 deletions

View File

@ -1,6 +1,6 @@
[book] [book]
authors = ["monoid"] authors = ["monoid"]
language = "en" language = "ko"
multilingual = false multilingual = false
src = "src" src = "build"
title = "Software Requirement Specification" title = "Software Requirement Specification"

10
cli.py
View File

@ -7,22 +7,22 @@ import os
def build(args): def build(args):
parser = argparse.ArgumentParser(description='Compiling the documentation') parser = argparse.ArgumentParser(description='Compiling the documentation', prog="cli.py build")
parser.add_argument('-v', '--verbose', action='store_true', help='verbose mode') parser.add_argument('-v', '--verbose', action='store_true', help='verbose mode')
parser.add_argument('--update_issues', action='store_true', help='update issues') parser.add_argument('--update_issues', action='store_true', help='update issues')
parser.add_argument('--outDir', default="build", help='output directory')
args = parser.parse_args(args) args = parser.parse_args(args)
if args.verbose: if args.verbose:
print("build start") print("build start")
if args.update_issues: if args.update_issues:
if args.verbose: if args.verbose:
print("get issues") print("get issues")
p = subprocess.run(["deno", "run", "-A","tools/getIssue.ts", "--path","./build/issues.json"]) p = subprocess.run(["deno", "run", "-A","tools/getIssue.ts", "--path",os.path.join(args.outDir,"/issues.json")])
p.check_returncode() p.check_returncode()
if args.verbose: if args.verbose:
print("build issues") print("build issues")
p = subprocess.run(["deno", "run", "-A","tools/printDocument.ts", "--overall", "--path", "./build/issues.json", "--outpath", "./build/overall.md"]) p = subprocess.run(["deno", "run", "-A","tools/printDocument.ts", "--issue_path", "./build/issues.json", "--outDir", args.outDir])
p.check_returncode()
p = subprocess.run(["deno", "run", "-A","tools/printDocument.ts", "--issue_path", "./build/issues.json", "--outpath", "./build/specific.md"])
p.check_returncode() p.check_returncode()
def help(_args): def help(_args):

View File

@ -1,120 +0,0 @@
# 2. 전체 시스템 개요(Overall description)
### 2.1. 제품 관점(Product perspective)
### 2.1.1. 시스템 인터페이스(System interfaces)
본 시스템은 Cross-platform 소프트웨어이다. 다음과 같은 브라우저가 원활히 실행될 수 있는 시스템에서 동작 할 수 있다.
- Chrome 버전 61 이상
- Firefox 버전 60 이상
- Edge 버전 79 이상
- Safari 버전 11 이상
- Chrome for Android 버전 100 이상
- Samsung internet 버전 8.2 이상
### 2.1.2. 사용자 인터페이스(User interfaces)
웹으로 동작하는 GUI이다. 키보드와 마우스, 터치 인터페이스로 동작할 수 있다. GUI의 디자인은 Material Design이나 Metro Design 같이 플랫한 디자인을 추구한다.
### 2.1.3. 하드웨어 인터페이스(Hardware interfaces)
해당되지 않음.
### 2.1.4. 소프트웨어 인터페이스(Software interfaces)
이 프로젝트의 결과물은 클립보드를 통해서 여러 타입의 데이터를 import/export한다.
### 2.1.5. 통신 인터페이스(Communications interfaces)
해당되지 않음.
### 2.1.6. 메모리 제약사항(Memory constraints)
해당되지 않음.
### 2.1.7. 운영(Operations)
해당되지 않음.
### 2.1.8. 사이트 적용 요건(Site adaption requirements)
해당되지 않음.
## 2.2. 제품 기능(Product functions)
본 프로젝트의 결과물은 다음과 같은 기능을 수행한다.
### 2.2.1 Chunk Operation
1. #1 Chunk: Focus/Unfocus
2. #2 Chunk: remove
3. #3 Chunk: read
4. #4 Chunk: previews
5. #10 Chunk: autocomplete
6. #11 Chunk: swap positions
7. #27 Chunk: edit
### 2.2.2 Document Operation
1. #5 Document: view Chunk
2. #6 Document: remove
3. #7 Document: add/delete tag
4. #8 Document: Drag And Drop Upload
5. #9 Document: Auto-Refresh
6. #12 Document: Share
7. #13 Document: Navigator
### 2.2.3 File Operation
1. #14 File: create/delete/rename file
2. #15 File: upload/download files
3. #18 File: export document
### 2.2.4 Search Operation
1. #16 Search: Document Search
### 2.2.5 Stash Operation
1. #17 Stash: read
2. #19 Stash: add
3. #20 Stash: remove
4. #21 Stash: Drag and Drop to Document
### 2.2.6 Management Operation
1. #22 Management: Login
2. #23 Management: Configure
3. #24 Management: Localization
4. #25 Management: Theme
### 2.2.7 Extension Operation
1. #28 Extension: API
2. #29 Extension: Plugin
### 2.2.8 비기능적 기능
- Docker 배포
- .env 설정
- 첫 로드후 로딩 0.5s 이내
- 동시 편집 이용자 5명 이내
- 1000 RPS 정도 버티기
## 2.3. 사용자 특성(User characteristics)
사용자는 기본적인 GUI 조작을 할 줄 알며 인터넷 사용을 원활히 할 수 있고 기본적인 영어를 읽고 쓸 줄 알며, markdown을 작성할 수 있는 사용자로 한정한다. 일반적으로 13세 이상 65세 이하의 사람을 사용자로 가정한다.
## 2.4. 제약사항(Constraints)
- 이 프로젝트는 MIT License로 개발되고 있으므로 라이브러리의 라이센스도 신경을 쓴다.
- XSS 공격에 안전해야 한다.
- 1000 RPS에서 문제없이 작동한다.
- 첫 로드후 로딩하면 0.5s 이내에 동작해야합ㄴ.다
- 동시 편집 이용자를 5명까지는 허용해야 합니다.
## 2.5. 가정 및 의존성(Assumptions and dependencies)
해당되지 않음.
## 2.6. 단계별 요구사항(Apportioning of requirements)
해당되지 않음.

View File

@ -1,6 +0,0 @@
# Summary
- [Introduction](./introduction.md)
- [Overall Description](./OverallDescription.md)
- [Specific Requirement](./SpecificRequirements.md)
- [Supporting information](./SupportingInformation.md)

View File

@ -1,439 +0,0 @@
# 3. 상세요구사항(Specific Requirements)
> - 설계자가 요구사항을 만족하는 시스템을 설계할 수 있도록 모든 요구사항을 상세하게 포함해야 한다.
> - 테스터가 시스템이 위 요건을 충족하는지 테스트해야 한다.
> - 모든 요구사항은 사용자, 운영자, 다른 외부 시스템에 의해 외부적으로 인지할 수 있어야 한다.
> - 이 요구사항에는 시스템에 대한 모든 입력(자극)과 출력(응답) 그리고 입력 또는 출력 지원에 대한 응답으로 실행되는 모든 기능에 관한 설명이 포함되어야 한다.
> - 상세 요구사항을 작성하기 위한 원칙
> 1. 상세 요구사항은 "Characteristics of a good SRS"에 설명한 모든 특성을 준수하도록 작성되어야 한다.
> 1. 상세 요구사항은 관련이 있는 이전 문서들과 상호 참조되어야 한다.
> 1. 모든 요구사항은 고유하게 식별할 수 있어야 한다.
> 1. 가독성을 높이기 위해 요구사항을 구성할 때 주의를 기울여야 한다.
## 3.1. 외부 인터페이스 요구사항(External interface requirements)
해당되지 않음.
## 3.2. 기능 요구사항(Functional requirements)
### (1) Chunk: Focus/Unfocus
액터: 사용자
시작 조건: Chunk를 편집할 수 있는 권한을 가져야 한다.
목표: 지금 편집하고자 하는 Chunk를 보여준다.
1. 사용자가 Chunk의 영역에 클릭을 했을때, Focus 된다. 그떄 다른 Chunk의 Focus를 사라지게 한다.
2. Focus를 얻었을때, Focus를 얻은 Chunk을 눈에 띄이도록 표시한다.
3. Focus가 사라졌을때, 변경되었으면 변경된 Chunk를 저장한다.
### (2) Chunk: remove
액터: 사용자
시작 조건: Chunk를 수정가능한 권한을 가지고 있어야함.
목표: Chunk를 지운다.
1. Chunk의 좌측 상단의 Context Menu에 삭제 아이콘을 클릭할 때나 빈 내용의 Chunk에서 <kbd>Backspace</kbd><kbd>Del</kbd>를 입력할 때 시작한다.
2. 해당 Chunk를 삭제한다.
3. 서버에서 그 Chunk를 삭제한다.
4. 아래의 Chunk가 있다면 끌어 올린다.
### (3) Chunk: read
액터: 사용자
시작조건: 없음
목표: Chunk를 보여준다.
1. 서버에서 내용을 읽는다.
2. 그 내용을 chunk안 영역에 사람이 보기 좋게 그 타입에 따라 렌더링한다.
render하는 대상 목록은 다음과 같다.
- markdown
- latex
- link (image, video, site)
- FEN
- etc
대안 흐름:
A. 렌더링 실패
1. 렌더링 실패에 실패하면 실패의 이유를 보여준다.
### (4) Chunk: previews
액터: 사용자
사용조건: 편집 중일때
목표: 미리보기를 보여주어 편집을 편하게 한다.
1. Chunk의 내용을 바꾸면 시작된다.
2. 보기모드에서 어떻게 보여질지 미리보기 창을 띄워준다. 미리보기는 기본적으로 하단에 띄우고 밑에 공간이 없으면 상단에 띄운다.
3. 내용이 바뀌면 미리보기 창의 내용도 갱신한다.
### (5) Document: view Chunk
액터: 사용자
시작조건: 읽기 권한이 있어야 한다.
목표: Chunk들을 보여준다.
1. Document가 로딩되면 시작한다.
2. 경로가 주어지면 Document Component에서 그 경로의 문서를 읽고 파싱한다. 그동안 로딩 바를 보여준다.
3. 로딩이 완료되면 파싱된 결과물인 Chunk들을 보여준다.
대안흐름:
A. 읽기 실패:
1. 읽기에 실패한 경우 읽기에 실패한 이유를 띄운다.
B. 파싱 실패:
1. 파싱에 실패한 경우 파싱에 실패한 이유를 띄우고 raw text가 담긴 Chunk로 렌더링한다.
### (6) Document: remove
액터: 사용자
시작조건: 문서를 삭제할 권한이 있어야함.
목표: 앱에서 문서를 삭제한다.
1. Document의 AppBar에 놓여있는 삭제 아이콘을 클릭하면 시작한다.
2. 정말로 삭제하겠냐는 다이얼로고가 띄운다.
3. 거기서 예스를 누르면 Document를 삭제한다.
대안 흐름:
1. 다이얼로그에서 아니오를 누르면 다이얼로고를 닫고 종료한다.
### (7) Document: add/delete tag
액터: 사용자
시작조건: 태그 수정 권한이 있을 때
목표: 문서의 태그를 추가/수정/삭제한다.
1. Document의 AppBar에 놓여있는 태그 수정 아이콘을 클릭하면 시작한다. 태그 수정 다이얼로그를 띄운다.
2. 태그 수정 다이얼로그에서 태그를 생성, 삭제한다.
3. 수정을 완료하고 저장 버튼을 누르면 태그 수정이 종료된다.
대안 흐름:
1. 취소 버튼을 누르면 다이얼로그를 닫고 종료한다.
### (8) Document: Drag And Drop Upload
액터: 사용자
시작조건: 문서 수정 권한이 있어야 한다.
목표: 업로드를 드래그 앤 드롭으로 한다.
1. 웹사이트의 그림이나 비디오 등의 파일을 Drag And Drop 해서 Chunk 사이에 놓으면 시작된다.
2. Drag And Drop된 파일을 서버에 업로드한다. 업로드시 파일 이름이 중복될 때 파일 이름이 밑줄과 숫자로 끝나지 않으면 이름의 뒤에 "_1"을 붙여 업로드 한다. 숫자로 끝나면 다음 숫자를 붙여서 업로드 한다. 파일 이름이 없다면 임의의 이름을 붙여서 업로드 한다.
3. 그 파일을 새로운 Chunk로 추가한다. 이때 웹에서 표시가능한 파일(이미지, 동영상)이면 파일을 표시하는 Chunk를 추가하고 아니면 다운로드 링크를 가진 Chunk를 추가한다.
대체흐름:
A. 파일 사이즈 큼
1. 기본단계 2에서 파일 사이즈가 설정보다 크면 시작한다.
2. 파일 크기가 너무 크다는 메세지로 띄우고 종료한다.
B. 작은 파일 사이즈
1. 기본단계 2에서 파일 사이즈가 설정보다 작으면 시작한다.
2. 파일을 base64로 인코딩해서 Chunk로 삽입한다.
### (9) Document: Auto-Refresh
액터: 외부 편집기
시작조건: 없음
목적: 변화를 실시간으로 따라갈 수 있게 한다.
1. Document나 Document가 포함하는 미디어의 파일이 다른 편집 프로그램에 의해서 변경되었을 시에 시작한다.
2. 보고 있는 사용자의 Document 뷰를 변경 부분만 Refresh한다. 이때 보고 있던 스크롤이 변하지 않게 유의한다.
### (10) Chunk: autocomplete
액터: 사용자
시작조건: chunk 수정시어야 한다.
목표: 링크 등을 자동으로 완성해서 편집을 편하게 한다.
1. <kbd>Ctrl+Space</kbd>로 자동완성 창을 띄울 수 있다.
2. 방향키로 고른다.
3. <kbd>Tab</kbd>이나 <kbd>Enter</kbd>를 통해 선택한다.
4. 선택한 단어로 완성시킨다.
### (11) Chunk: swap positions
액터: 사용자
시작 조건: Document 수정권한이 있어야 한다.
목적: 앱에서 Chunk 위치를 바꿀 수 있다.
1. Focus를 얻고 핸들 아이콘을 누를때 시작한다.
2. 이때 오버레이를 표시해서 놓여졌을 때의 상황을 미리 볼 수 있게 한다.
3. 드래그해서 원하는 장소에 놓으면 위치를 바꿀 수 있다.
### (12) Document: Share
액터: 사용자
시작 조건: 문서를 공유할 수 있는 권한을 가져야한다.
목표: 문서를 공유한다.
1. Document의 AppBar에 놓여있는 공유 아이콘을 누르면 시작한다.
2. 공유 링크를 복사한다. 그리고 공유 설정아이콘을 띄워준다. 여기서 종료할 수 있다.
3. 공유 설정아이콘을 클릭하면 공유 설정 다이얼로그를 띄운다. 이 다이얼로그에서는 공유 기간과 편집 가능여부 등을 설정할 수 있고 공유 링크를 복사할 수 있다. 공류를 취소할 수도 있다.
### (13) Document: Navigator
액터: 사용자
시작 조건: 없음
목표: 문서들을 쉽게 이동할 수 있는 네비게이터를 보여준다.
1. 만일 문서가 속하는 디렉토리에 Summary.md 가 있고 올바른 형식(링크와 리스트로 이루어져 있음)이면 시작한다.
2. Document의 왼쪽에 Summary의 내용을 네비게이터 역할로 표시한다.
### (14) File: create/delete/rename file
액터: 사용자
시작조건: 디렉토리에 대한 권한을 가지고 있어야한다.
목표: 앱상에서 파일을 생성하거나 삭제 할 수 있어야 한다.
1. Treeview에 포커스가 간 상태에서 시작한다.
2. Treeview에서 오른쪽 클릭을 하면 Context Menu가 나오고 새파일을 클릭하면 이름을 지정해서 파일을 생성할 수 있다.
3. Context Menu에서 삭제를 클릭하면 해당 파일을 삭제한다.
4. 이름 바꾸기를 클릭하거나 Treeview에서 파일에 포커스가 간 상태에서 <kbd>F2</kbd>를 입력하면 이름을 바꿀 수 있도록 한다.
### (15) File: upload/download files
액터: 사용자
시작조건: 디렉토리의 권한이 있어야 한다.
목표: 파일을 업로드하거나 다운로드 할 수 있어야 한다.
1. Treeview의 Context menu에서 다운로드 버튼을 클릭해서 다운로드 할 수 있다.
2. Treeview에 파일을 드래그 앤 드롭하는 것으로 업로드 할 수 있다.
### (16) Search: Document Search
액터: 사용자
시작조건: 문서를 읽을 수 있는 권한이 있어야 한다.
목표: 문서나 문서들을 검색할 수 있다.
1. Drawer에서 문서 검색 버튼을 누르면 문서 검색 창이 뜬다.
2. 문서 검색창에서 범위를 지정한다. 기본 범위는 현재 보고 있는 문서로 한다.
3. 문서 검색 창에서 태그를 검색할지 내용으로 검색을 할지 지정한다. 기본값은 내용이다.
4. 정규식을 사용할 것인지 지정한다. 기본값은 사용 안함이다.
5. 검색 버튼을 누르면 해당 조건을 만족하는 문서를 리스트로 보여준다.
### (17) Stash: read
액터: 사용자
시작조건: 화면크기가 768px 이상일때 보여준다.
목표: Stash를 보여준다.
1. 오른쪽에 작은 버튼을 두고 버튼을 클릭하면 시작한다.
2. 오른쪽 Drawer가 열려서 Stash의 내용을 보여준다. 최대 지정된 숫자만큼의 내용들을 보여준다.
3. 다시 버튼을 누르면 Stash Drawer를 닫는다.
### (18) File: export document
액터: 사용자
시작조건: 문서를 읽을 수 있는 권한이 있어야 한다. 문서 타입에만 가능하다.
목표: 문서를 보기 모드에서 보이는 것처럼 출력할 수 있다.
1. 메뉴의 Context menu에서 접근 할 때 시작한다.
2. 출력하기를 누르면 출력 다이얼로그가 뜬다.
3. 출력할 문서 타입을 문서 타입을 설정한다. 출력할 수 있는 문서 타입은 다음과 같다.
- pdf
- html
4. 출력하기를 누르면 출력된 문서를 다운로드한다.
대안흐름:
A. 취소
1. 단계 2에서 시작한다.
2. 취소하기를 누르면 다이얼로그 창을 닫고 종료한다.
### (19) Stash: add
액터: 사용자
시작 조건: Stash 창을 연 상태에서 포커스가 Stash 창에 주어져 있어야 한다.
목표: Stash를 추가한다.
1. \<\< 포함 #17 \>\>
2. <kbd>Ctrl+V</kbd>를 누르면 Stash에 클립보드의 내용이 Stash로 추가되고 클립보드는 비워진다.
3. <kbd>Ctrl+Z</kbd>를 눌러서 추가를 되돌릴 수 있다.
### (20) Stash: remove
액터: 사용자
시작조건: Stash 창을 연 상태에서 포커스가 Stash 창에 주어져 있어야 한다.
목표: 원하는 Stash를 삭제한다.
1. Stash 창의 각각 항목의 삭제 아이콘을 클릭하면 선택된 항목을 삭제한다.
2. Stash에 붙어있는 삭제 아이콘을 클릭하면 전체 항목을 삭제한다.
3. <kbd>Ctrl+Z</kbd>를 눌러서 삭제를 되돌릴 수 있다.
### (21) Stash: Drag and Drop to Document
액터: 사용자
시작 조건: 문서 편집 권한이 있어야 한다.
목표: 드래그 앤 드롭으로 Chunk를 Stash에서 꺼내 삽입할 수 있다.
1. Stash 창의 Stash을 Document에 드래그하면 시작된다.
2. Document의 Chunk 사이에 Stash을 드롭하면 그 자리에 Chunk가 삽입된다. 사이의 결정은 제일 가까운 청크로 정한다.
3. Stash을 그 위치로 업로드시킨다. 업로드는 #8 와 한 것 같이 한다.
4. 해당 Stash를 Stash창에서 삭제한다.
대안흐름:
A. 취소
1. Stash 창에 놓으면 작업을 취소한다.
### (22) Management: Login
액터: 사용자
시작조건: 없음.
목표: 사용자가 액세스하기 위해 로그인할 수 있다.
1. 사용자가 로컬에서 지정된 프로그램이 아닌 외부에서 접근한다면 시작한다.
2. 로그인 암호를 요구한다. 초기 로그인 암호는 환경변수에 의해서 결정된다.
3. 알맞은 암호를 입력했다면 권한을 부여한다.
### (23) Management: Configure
액터: 사용자
시작조건: 없음.
목표: 앱 정책등에 대해 앱에서 설정할 수 있다.
1. 편집기 내부에서 설정 아이콘을 클릭하면 설정창을 보여준다. 설정창은 프로그램의 속성을 설정할 수 있고 로그를 볼 수 있다. 설정창은 다음 항목들을 포함한다.
- 로그인 암호
- 테마 설정
- 언어 설정
이것은 권한에 따라 선택적으로 렌더링된다.
2. 다시 설정 아이콘을 클릭하면 설정창을 닫는다.
### (24) Management: Localization
> 어플리케이션을 여러가지 다양한 언어로 제공한다.
> 다음은 다른 언어로 바꾸는 사용 사례이다.
액터: 사용자
시작조건: 없음.
목표: 설정창에서 다른 언어로 바꿀 수 있다.
1. 설정창을 연다.
2. 언어 항목으로 간다. 지원되는 언어 리스트 창이 놓여저있다.
3. 언어 항목에서 다른 언어로 바꾼다. 이때 창을 다시 렌더링한다.
### (25) Management: Theme
액터: 사용자
시작조건: 없음.
목표: 설정창에서 테마를 설정할 수 있다.
1. 설정창에서 테마로 이동한다.
2. 기본적으로 제공하는 밝은 테마과 어두운 테마를 고른다. 기본값은 밝은 색이다. 바꾸는 즉시 테마를 변경한다.
3. 커스텀 css 를 올려서 테마로 등록한다.
### (27) Chunk: edit
액터: 사용자
시작조건: Chunk의 Focus를 얻어야 한다.
목표: Chunk안의 컨텐츠를 수정할 수 있다.
1. 수정가능한 타입인지 확인한다.
2. 타입에 맞는 에디터를 띄운다. 예를 들어 text 타입이면 해당 Chunk 안의 text를 수정할 수 있게 한다.
### (28) Extension: API
액터: API 사용자
시작조건: 없음.
목표: 외부에서 API를 가지고 접근가능하도록 인터페이스를 제공한다.
1. 설정에 들어가서 API 토큰을 발급받는다.
2. api를 사용할때 Header에 발급받은 토큰을 넣고 통신한다.
### (29) Extension: Plugin
액터: 사용자
시작 조건: 없음
목표: Plugin으로 편집환경을 확장 가능하게 한다.
1. 플러그인을 폴더에 추가해 플러그인을 설치한다.
2. 플러그인을 사용한다.
> - 기능 요구사항은 소프트웨어가 입력을 처리하고 출력을 생성하는 기본적인 행동을 정의해야 한다.
> - 포함하는 행동들
> 1. Validity checks on the inputs
> 1. Exact sequence of operations
> 1. Responses to abnormal situations, including
> 1. Overflow
> 1. Communication facilities
> 1. Error handling and recovery
> 1. Effect of parameters
> 1. Relationship of outputs to inputs, including
> 1. Input/output sequences
> 1. Formulas for input to output conversion
## 3.3. 성능 요구사항(Performance requirements)
> - 소프트웨어 또는 소프트웨어와 사람의 상호작용에 대하여 수치화된 정적/동적 요구사항이 명시되어야 한다.
> - 수치화된 정적 요구사항의 종류
> 1. 지원할 터미널 수
> 1. 지원할 동시 접속 사용자 수
> 1. 처리할 정보의 양과 유형작업 및 데이터의 양
## 3.4. 논리적 데이터베이스 요구사항(Logical database requirements)
> - 데이터베이스에 저장할 정보에 관한 논리적 요구사항을 지정해야 한다.
> - 논리적 요구사항의 종류
> 1. Types of information used by various functuons
> 1. Frequency of use
> 1. Accessing capabilities
> 1. Data entities and their relationships
> 1. Integrity constraints
> 1. Data retention requirements
## 3.5. 설계 제약사항(Design constraints)
> - 다른 표준, 하드웨어 한계 등에 의해 부과될 수 있는 설계 제약사항을 명시해야 한다.
### 3.5.1. 표준 준수(Standards compliance)
해당되지 않음.
## 3.6. 소프트웨어 시스템 속성(Software system attributes)
> - 요구사항으로 사용될 수 있는 소프트웨어의 여러 가지 속성 중 제품이 객관적으로 입증되는 데 필요한 속성을 명시해야 한다.
### 3.6.1. 신뢰성(Reliability)
> - 배포될 때 소프트웨어 시스템의 필수 신뢰성을 확립하는 데 필요한 요소를 명시해야 한다.
### 3.6.2. 가용성(Availability)
> - 검사, 복구, 재시작과 같이 전체 시스템에 대해 정의된 가용성 수준을 보장하는 데 필요한 요소가 지정되어야 한다.
### 3.6.3. 보안성(Security)
> - 실수 또는 악의적인 접근, 사용, 수정, 파괴, 공개로부터 소프트웨어를 보호하기 위한 요소를 명시해야 한다.
> - 포함될 수 있는 요구사항
> 1. Utilize certain cryptographical techinques
> 1. Keep specific log or history data sets
> 1. Assign certain functions to diffrent modules
> 1. Restrict communication between some areas of the program
> 1. Check data integrity for critical variables
### 3.6.4. 유지 보수성(Maintainability)
> - 소프트웨어 자체를 쉽게 유지 보수할 수 있는 속성을 명시해야 한다.
> - 모듈화, 인터페이스, 복잡성 등과 관련된 요구사항이 있을 수 있다.
### 3.6.5. 이식성(Portability)
해당되지 않음.
## 3.7. 상세 요구사항의 구성(Organizing the specific requirements)
> - 시스템의 세부 요구사항은 광범위한 경향이 있으므로 자료를 이해하기에 가장 적합한 방식으로 구성하는 방법을 세심하게 고려해야 한다.
### 3.7.1. 시스템 모드(System mode)
> - 일부 시스템은 운영 모드에 따라 상당히 다르게 작동할 수 있다.
> - 예: 제어 시스템은 연습, 일반, 긴급 등의 여러 모드가 있을 수 있다.
### 3.7.2. 사용자 부류(User class)
> - 일부 시스템은 사용자의 부류에 따라 서로 다른 기능을 제공한다.
> - 예: 엘리베이터 제어 시스템은 승객, 정비원, 소방관에게 서로 다른 기능을 제공한다.
### 3.7.3. 객체(Objects)
> - 객체는 시스템에서 현실 세계와 대응되는 개체이다.
> - 객체에는 각 각체의 상태(attributes) 및 객체의 행위(functions)가 포함된다.
> - 이러한 행위는 services, methods, processes라고도 한다.
### 3.7.4. 특징(Feature)
> - 특징은 시스템에 의해 외부적으로 요구되는 서비스로서 원하는 결과를 얻기 위해서는 입력이 필요할 수도 있다.
> - 예: 전화 시스템에서 특징들은 지역 내 통화, 착신 전환, 화상 통화를 포함한다.
> - 일반적으로 각 특징은 자극-반응의 순서로 설명된다.
### 3.7.5. 자극(Stimulus)
> - 일부 시스템은 자극의 측면에서 기능들을 설명할 때 가장 잘 구성될 수 있다.
> - 예: 항공기 자동 착륙 시스템은 동력 상실, 윈드시어 등을 위해 구성될 수 있다.
### 3.7.6. 반응(Response)
> - 일부 시스템은 반응 생성을 지원하는 기능들을 설명할 때 가장 잘 구성될 수 있다.
> - 예: 직원 시스템의 기능은 급여 생성과 관련된 기능들, 직원 목록 생성과 관련된 기능 등으로 구성될 수 있다.
### 3.7.7. 기능 계층(Functional hierarchy)
> - 위 조직 체계 중 유용한 수단이 없다면, 전체 기능은 공통 입력, 공통 출력 또는 공통 내부 데이터 접근에 의해 구성된 기능의 계층으로 구성될 수 있다.
> - 데이터 흐름 다이어그램과 데이터 사전을 사용하여 기능과 데이터 사이의 관계를 보여줄 수 있다.
### 3.7.8. Additional comments
> - 새로운 SRS를 고려할 때 두 가지 이상의 조직 기법이 적합할 수 있다.
> - 이 경우 명세에 따른 시스템의 상세 요구사항에 맞춘 다중 계층의 요구사항을 구성한다.

View File

@ -21,7 +21,6 @@ deno run --allow-read --allow-write printDocument.ts --overall --path ./issues.j
으로 실행하면 됩니다. 으로 실행하면 됩니다.
다음과 같은 인자를 가집니다: 다음과 같은 인자를 가집니다:
- `overall`: overall을 출력 - `outDir`: 지정된 경로에 출력. 설정되지 않으면 `stdout`에 출력함.
- `outpath`: 지정된 경로에 출력. 설정되지 않으면 `stdout`에 출력함.
- `issue_path`: json 파일 위치. 지정되지 않으면 `stdin`에서 읽으려고 시도. - `issue_path`: json 파일 위치. 지정되지 않으면 `stdin`에서 읽으려고 시도.
- `w`, `watch`: 파일에 변경이 있을 때 자동으로 업데이트. - `w`, `watch`: 파일에 변경이 있을 때 자동으로 업데이트.

View File

@ -3,7 +3,7 @@ import { Issue } from "./githubType.ts";
import { readAll } from "https://deno.land/std@0.135.0/streams/mod.ts" import { readAll } from "https://deno.land/std@0.135.0/streams/mod.ts"
import { parse as argParse } from "https://deno.land/std@0.135.0/flags/mod.ts"; import { parse as argParse } from "https://deno.land/std@0.135.0/flags/mod.ts";
import { normalize, join as pathJoin, fromFileUrl } from "https://deno.land/std@0.135.0/path/mod.ts"; import { normalize, join as pathJoin, fromFileUrl } from "https://deno.land/std@0.135.0/path/mod.ts";
import * as Eta from "https://deno.land/x/eta/mod.ts"; import * as Eta from "https://deno.land/x/eta@v1.12.3/mod.ts";
async function readContent(path?: string): Promise<string> { async function readContent(path?: string): Promise<string> {
let content = "[]"; let content = "[]";
@ -19,49 +19,66 @@ async function readContent(path?: string): Promise<string> {
return content; return content;
} }
async function readAndPrint(args: { type DocType = "overall.md" | "specific.md" |"intro.md" | "SUMMARY.md" | "support.md";
path?: string, const targets: DocType[] = ["SUMMARY.md", "overall.md", "specific.md", "intro.md", "support.md"];
overall?: boolean,
outpath?: string type printDocParam = {
target: DocType,
data:{
issues: Issue[]
}
};
async function printDoc(param: printDocParam,option? : {
outDir?: string
}){ }){
const c = await readContent(args.path); option = option ?? {};
const issues = JSON.parse(c) as Issue[]; const {target , data } = param;
issues.sort((a, b) => a.number - b.number); const { outDir } = option;
let print: string = ""; let print: string = "";
if (args.overall) { print = await Eta.renderFile(target, data) as string;
print = await Eta.renderFile("overall.md", { if (outDir) {
issues: issues const outPath = pathJoin(outDir, target);
}) as string; await Deno.mkdir(pathJoin(outDir), { recursive: true });
} await Deno.writeTextFile(outPath, print);
else {
print = await Eta.renderFile("specific.md", {
issues: issues
}) as string;
}
if (args.outpath) {
Deno.writeTextFileSync(args.outpath, print);
} }
else { else {
console.log(print); console.log(print);
} }
} }
async function readAndPrint(args: {
issue_path?: string,
outDir?: string
}) {
const c = await readContent(args.issue_path);
const issues = JSON.parse(c) as Issue[];
issues.sort((a, b) => a.number - b.number);
for(const target of targets){
await printDoc({
target: target,
data: {
issues
}}
,{
outDir: args.outDir
});
}
}
async function main() { async function main() {
const parsedArg = argParse(Deno.args); const parsedArg = argParse(Deno.args);
const { issue_path, outpath, overall, w, watch } = parsedArg; const { issue_path, outDir, w, watch } = parsedArg;
const watchMode = w || watch; const watchMode = w || watch;
if (typeof issue_path !== "undefined" && typeof issue_path !== "string") { if (typeof issue_path !== "undefined" && typeof issue_path !== "string") {
console.log("Please provide a path to the json file."); console.log("Please provide a path to the json file.");
Deno.exit(1); Deno.exit(1);
} }
if (typeof outpath !== "undefined" && typeof outpath !== "string") { if (typeof outDir !== "undefined" && typeof outDir !== "string") {
console.log("Please provide a path to the output file."); console.log("Please provide a path to the output file.");
Deno.exit(1); Deno.exit(1);
} }
if (typeof overall !== "undefined" && typeof overall !== "boolean") {
console.log("Please provide a boolean value for overall.");
Deno.exit(1);
}
if (typeof watchMode !== "undefined" && typeof watchMode !== "boolean") { if (typeof watchMode !== "undefined" && typeof watchMode !== "boolean") {
console.log("Please provide a boolean value for w."); console.log("Please provide a boolean value for w.");
Deno.exit(1); Deno.exit(1);
@ -82,9 +99,9 @@ async function main() {
const c = await readContent(issue_path); const c = await readContent(issue_path);
const issues = JSON.parse(c) as Issue[]; const issues = JSON.parse(c) as Issue[];
issues.sort((a, b) => a.number - b.number); issues.sort((a, b) => a.number - b.number);
await readAndPrint({ path, outpath, overall }); await readAndPrint({ issue_path, outDir });
if (watchMode) { if (watchMode) {
const watcher = Deno.watchFs([viewPath, path as string]); const watcher = Deno.watchFs([viewPath, issue_path as string]);
for await (const event of watcher) { for await (const event of watcher) {
if (event.kind === "modify") { if (event.kind === "modify") {
Deno.stdout.write( Deno.stdout.write(
@ -92,9 +109,8 @@ async function main() {
); );
console.log(`reloading ${event.paths.join(", ")}`); console.log(`reloading ${event.paths.join(", ")}`);
readAndPrint({ readAndPrint({
path: path as string, issue_path: issue_path as string,
overall: overall as boolean, outDir: outDir as string
outpath: outpath as string
}); });
} }
} }

View File

@ -0,0 +1,6 @@
# Summary
- [Introduction](./intro.md)
- [Overall Description](./overall.md)
- [Specific Requirement](./specific.md)
- [Supporting information](./support.md)