타자 스크립트와 테스트 드라이브 디자인은 모든 문제를 해결할 수 없지만...
오랫동안 나는 테스트를 작성하거나 나중에 할 시간이 없다고 생각했다.나는 몇 년이 걸려서야 나의 생각이 어떻게 완전히 후퇴했는지 알게 되었다.
내가 빨리 너에게 그림을 그려줄게...
나는 반응이 둔한 사람이다
react가 angular에 이채를 띠었을 때, 나는 한번 보았지만, 잠시 바닐라 자바스크립트를 사용하기로 결정했다.레드ux가 상태 관리와 데이터 저장을 위한 편리한 해결 방안을 추가했을 때, 나는 여전히 로컬 저장소와 다른 모델을 사용하고 있다.
react와redux를 동시에 사용하기 시작했을 때 typescript를 보고 jsx 변체를 잠시 사용하기로 결정했습니다.심지어 나더러 구동 설계를 테스트하게 하지 마라...
무슨 변화가 생겼습니까?
이번에 나는 그 라이브러리, 언어, 업무 흐름을 완전히 반대하는 것은 아니다.나는 단지 개발자의 시야에 새로운 것을 처음 언급했을 때 마차에 뛰어오르지 않았을 뿐이다. 이런 태도는 나로 하여금 최근 몇 년 동안 틀의 피로를 면하게 했다.
또 다른 원인은 현실이다.만약 당신이 학생이 아니라면, 몇 안 되는 대형 IT 거두 중 한 명으로 일하거나, 자신의 일을 한다면, 당신은 남겨진 코드 라이브러리, 단일 프로젝트, 또는 긴박한 마감일에 얽매일 가능성이 높다.
우리 대다수의 사람들에게 새로운 프레임워크/라이브러리, 심지어 언어 (typescript는javascript의 초집합) 를 사용하기 시작하는 것은 불가능할 수도 있다. 우리가 퇴근 후에 프로젝트를 하거나 사장으로부터 약간의 회전 여지를 얻지 않으면.
몇 년 전, 내가 Das Büro am Draht에서 일하기 시작했을 때, 나는 이미react와redux에 익숙해졌다.우리는 한 팀으로 함께 앉았고, 후에 우리의 한 작업팀에 가입하여 typescript를 사용하는 장점을 토론했다.경영진은 typescript를 사용하는 것을 배우고 연습할 시간을 주었고, 모든 새로운 개발에 익숙해질 때까지 공부를 시작하는 과정에서 교부 속도를 늦추는 것에 동의했다.
그러나 테스트 구동 설계는 전혀 다른 것이다.typescript는 일정한 비용을 가져왔지만 관리하기 쉬워지고 일정 시간 후에 개발 시간에 영향을 주지 않는다.한편, 테스트 구동 개발...우선 그것을 여기저기 사용하는 것은 무의미하다.너는 너의 구성 요소가 정말로 그div를 나타냈는지 테스트할 계획이니?너는 네가 쓴 모든 구성 요소에 대해 빨간색에서 녹색으로 순환을 반복할 수 있니?몰라요.
또한 TDD는 당신이 새로운 것을 처음 개발할 때 더 많은 시간을 들여야 한다는 것을 의미한다. 해커 공격과 잠시 후에 테스트를 작성하면 당신이 더욱 빨리 발표하고...프로젝트가 주동적인 개발에서 유지보수/지원 모드로 전환된 적이 없으면, 이 테스트들은 영원히 마지막에 작성되지 않을 수도 있습니다.
TDD는 경영진이나 프로젝트 매니저에게 팔기 힘들다. 대부분의 경우, 당신이 그에게 말하지 않고 묵묵히 하지 않는 한 고객에게 동의를 얻는 것은 더 어렵다.
오늘은 달라졌어요.오늘 여기서 말씀드리지만 TDD는 그 용도가 있고 typescript와도 잘 어울립니다.왜?그것은 너로 하여금 생각하게 한다.
나는 이곳에서 당신들에게 우리 고객의 업무 논리를 보여줄 수 없지만, 나는 개인 프로젝트에서 그것을 설명하려고 시도할 것이다. 나는 퇴근 후에 이 프로젝트를 하는 것은 재미를 위해서이다.아래의 예에서 저는 위조 인공지능의 기초를 구축하여 설정 가능한 매개 변수 집합에 따라 의사결정 모델의 결과를 확정할 것입니다.이것은 기본적으로 게임 속의 영웅에게 어떻게 미리 정의된 규칙에 따라 목표, 기능과 주문을 선택하는지 알려주는 방법이다.
보통 나는 앉아서 기초 지식을 간단하게 쓰고 거기서부터 시작한다.만약 유효하다면, 그것을 보존하고 확장하십시오.없는 경우 버리고 다시 시도하십시오.나는 이전에 빠른 원형에 관한 글을 쓴 적이 있다. 나는 여전히 열광적인 팬이다. 그러나 이번에는 내가 원하는 결과에 대해 매우 명확한 생각을 가지게 되었다. 그래서 나는 앉아서 앞에서 언급한 도구를 사용하여 미리 계획을 세울 수 있다.
나의 과정
나는 나의 과정을 다음과 같은 몇 가지 절차로 나눈다.
If you have no clue what I'm talking about when I mention gambits or unit behaviour rules, think of characters in a strategy / role playing game that need to decide what to do next based on rules. The enemy might attack the player or use a healing spell when his hitpoints are below a certain level... that sort of thing.
이 예는 무엇이 필요합니까?나는 그것을 맞추어 썼다.이것은 내가 첫 번째 코드를 쓰기 전에 종이나 스마트폰에서 자주 하는 걸음이다.
1) 종이 원형
우리의 다음 단계는 이 전체적인 사고방식을 우리가 실현할 수 있는 기능에 응용하는 것이다.
2) 빈 함수
/* processBehaviourChain()
* - check all gambits in the behaviour chain for a match
*/
/* getAvailableTargets()
* - get all targets matching the target type
*/
/* getMatchingTargets()
* - return only targets matching the selection criteria
*/
/* isActionAvailable()
* - check if the action is possible
* - (enough resources, material and so on)
*/
/* compareTargetHP()
* - check if the current target matches the hitpoint condition
*/
/* compareTargetStatus()
* - check if the current target matches the status condition
*/
보시다시피 이 초도를 읽는 것만으로도 언제 무슨 일이 일어날지, 왜 일어날지 잘 알고 있습니다.모든 함수는 적당한 명칭이 있습니다. (일부 함수는 실현 과정에서 변화가 발생할 수 있습니다.) 이 함수들이 무엇을 해야 하는지 잘 이해할 수 있습니다.3) 타자 스크립트 유형
// We need units to compare and some stats and status to check.
// I will skill the imported 'Effect' and 'RaceName' types here
type UnitBase = {
hp: {
current: number;
max: number;
};
status: Effect[];
};
export type Unit = UnitBase & {
name: string;
id: string;
race: RaceName;
};
// possible selections for targeets and derived types
const targets = [
"self",
"currentAlly",
"currentEnemy",
"leader",
"leaderCurrentEnemy",
"leaderCurrentAlly"
] as const
type Target = typeof targets[number];
const conditionTargets = [
...targets,
"ally",
"enemy",
] as const
type ConditionTarget = typeof conditionTargets[number];
/*
* skipped a few more types here including a selection of
* valid absolute numbers and percentage values as well as
* our previously used Effect type
*/
// comparison operators for numerical values like hitpoints
const comparisonOperators = ["lt", "lte", "eq", "gte", "gt"] as const
type ComparisonOperator = typeof comparisonOperators[number];
type PercentageComparison = [ComparisonOperator, Percentage];
type AbsoluteComparison = [ComparisonOperator, AbsoluteValue];
type StatusComparison = [boolean, Effect];
// last thing to do here is a simple mapping of valid combinations
type TargetComparison =
| ["hp", AbsoluteComparison]
| ["hp%", PercentageComparison]
| ["mp", AbsoluteComparison]
| ["mp%", PercentageComparison]
| ["status", StatusComparison]
type TriggerCondition = [ConditionTarget, TargetComparison];
type Gambit = {
target: ConditionTarget;
comparison: TargetComparison;
action: Spell | Skill | Item;
}
함수를 만들어서 이 유형들을 충분히 활용합시다.const processBehaviourChain = (units: Unit[], gambits: Gambit[]): void => {
// check all gambits in the behaviour chain for a match
}
const getAvailableTargets =(units: Unit[], targetType:ConditionTarget): Unit[] | null => {
// get all targets matching the target type
}
const getMatchingTarget = (targets: Unit[], comparison: TargetComparison): Unit | null => {
// return only targets matching the selection criteria
}
const isActionAvailable = (actor: Unit, action: Action): boolean => {
// check if the action is possible
// (enough resources, material and so on)
}
const compareTargetHP = (target: Unit, comparison: TargetComparison): boolean => {
// check if the current target matches the hitpoint condition
}
const compareTargetStatus = (target: Unit, comparison: TargetComparison): boolean => {
// check if the current target matches the status condition
}
보시다시피, 우리는 정의 형식을 통해 코드에 많은 자신감을 얻었습니다.우리는 지금 테스트에서 무엇을 얻고 싶습니까?만약 우리가 생성한 출력이 우리의 형식과 일치하지 않는다면 typescript 컴파일러가 이 점을 포착할 것입니다.우리가 테스트를 작성한 것은 일정한 코드 커버율에 도달하기 위해서가 아니라 typescript가 볼 수 없는 구석을 검사하기 위해서입니다.만약 우리가 이 프레젠테이션 프로젝트를 위해 테스트를 실시한다면, 사용자 입력, 필터 응용 프로그램 (예를 들어 getavailableTargets () 과 함수 내부 복잡도 단계의 검증 문제를 검사할 것입니다. 일부 하위 함수를 호출했는지, 그리고 가장자리 상황을 정확하게 포착했는지 등을 포함합니다.
결론
나의 최초의 관점은 Typescript와 테스트 드라이브 디자인을 사용하면 네가 가지고 있는 문제에 대해 다른 생각을 하게 될 것이다.그것들은 인코딩을 시작하기 전에 심지 모형을 세우도록 미리 생각하게 한다.
천천히 할까요?
그래, 어느 정도는 늦어질 것이다. 설령 우리가 전체 프로젝트를 완성했다 하더라도, 우리의 준비에서 이익을 얻기 시작할 수 있을 것이다.TDD와 TS에 익숙하지 않으면, 테스트를 계획하고, 계산하고, 작성하는 데 시간이 좀 걸립니다. 하지만!
만약 프로젝트 개발 과정에서 당신이 계획 오류를 저질렀다는 것을 깨닫게 된다면, 어떤 부분을 조정해야 한다. 추가적인 상황, 서로 다른 데이터 또는 다른 상황을 고려하면, 당신은 곧 노동 성과를 거둘 것이다.Typescript 컴파일러의 관건적인 장점은 일부 코드를 재구성하거나 재설계할 때 누락될 수 있는 모든 부분을 지적하고 새로운 데이터 구조를 사용하더라도 그 중 어느 것도 누락되지 않도록 테스트하는 것이다.
계속하다
나는 곧 이pet 프로젝트의 실제 테스트를 상세하게 소개할 것이다. 그리고 너는 하나하나 나의 진도를 추적할 수 있다.
나는 Typescript 프로젝트를 더 큰 자신감으로 작성해 왔다. 나의 일부 프로젝트에 코드를 추가하기 전의 테스트는 나로 하여금 계획을 더욱 잘 생각하게 했다.나는 장래에 여러분과 이 경험을 나눌 수 있기를 바랍니다.
Reference
이 문제에 관하여(타자 스크립트와 테스트 드라이브 디자인은 모든 문제를 해결할 수 없지만...), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/allbitsequal/typescript-and-test-driven-design-don-t-fix-everything-but-38n2텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)