원시 미혹증의 치료 방법
20670 단어 csharpdesignpatterndotnetcodesmell
무엇이 원시적인 미치광이입니까?
우선, 원어는 대부분의 언어에서 사용할 수 있는 기본 데이터 형식이다.문자열, 숫자 (int,float), 브리 값 등 데이터 형식을 포함합니다.
원시 곤란은 일종의 코드 냄새이다. 이런 냄새에서 원시 데이터 유형은 데이터 모델을 나타내는 데 과도하게 사용된다.원어의 문제는 그것들이 매우 보편적이라는 것이다.예를 들어 문자열은 이름, 주소, 심지어 ID를 대표할 수 있습니다. 왜 이것이 문제입니까?
그들은 안정감을 잃었다.밧줄 한 가닥이 밧줄 한 가닥이다.컴파일러는 이름이나 주소를 나타내는 문자열을 전달했는지 알 수 없습니다.이것은 의외로 잘못된 필드에 값을 부여하기 쉽다는 것을 의미한다. 코드는 데이터가 완전히 혼란스러울 때까지 정상적으로 실행되고 컴파일될 것이다.
원시 미혹증을 치료하다
다음은 원시적으로 어려움을 겪는 Person 유형의 예입니다.
public class Person
{
public Person(string id, string firstName, string lastName, string address, string postcode, string city, string country)
{
// initialisation logic
}
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string PostCode { get; set; }
public string City { get; set; }
public string Country { get; set; }
public void ChangeAddress(string address, string postcode, string city, string country)
{
// change address logic
}
}
여기 왜 이래?우리는 완전히 문자열 속성으로 구성된 클래스가 있다.구조 함수는 긴 문자열 매개 변수로 구성되어 있습니다. 어느 순간 잘못된 값이 잘못된 매개 변수 슬롯에 분배될 것을 보장합니다.우리도 주소를 바꾸는 방법이 하나 있지만, 실제로 이런 논리는 Person 클래스가 책임져서는 안 된다.마지막으로 ID도 문자열이므로 다른 유형의 ID로 예기치 않게 사용될 수 있습니다.
그럼 우리 어떡하지?
우리가 먼저 보아야 할 것은, 어떤 속성이 한데 조합될 수 있느냐는 것이다.이것에 대한 좋은 테스트는 이 속성 중 어떤 것들이 함께 업데이트될 수 있습니까?예를 들어 주소, 우편 번호, 도시, 국가 필드는 분명히 그룹을 나누어야 한다. (이사를 가면 모든 속성이나 대부분의 속성이 함께 업데이트될 가능성이 높다.)그러면 우리는 이러한 속성을 그것들의 종류로 재구성할 것이다.
public class Address
{
public Address(string address, string postCode, string city, string country)
{
// initialisation logic
}
public string Address { get; set; }
public string PostCode { get; set; }
public string City { get; set; }
public string Country { get; set; }
}
public class Person
{
public Person(string id, string firstName, string lastName, Address address)
{
// initialisation logic
}
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
}
우리의 개인 수업은 보기에 이미 많이 좋아진 것 같다.주소와 관련된 모든 논리는address 클래스에 봉인되어 있으며, 우리는 구조 함수에서 많은 문자열 파라미터를 제거하려고 노력했다.
전체적으로 말하자면, 우리는 여전히 같은 수량의 문자열 속성을 가지고 있다는 것을 알 수 있습니다.최종적으로 데이터를 원어에 저장해야 할 수도 있기 때문에 매우 좋다.원시적인 미혹을 피하는 중요한 부분은 이러한 원시적인 요소를 정의가 좋은 대상에 봉하는 것이다. 이런 대상은 실제적으로 그들의 의미를 대표한다.
다음에 처리해야 할 것은 ID입니다. 유형 보안을 ID로 복원하기 위해서 이른바 강력한 유형 ID를 만들 수 있습니다. 간단히 말하면, 이것은 해당 실체에 특정한 용기 대상에 봉인된 기본값입니다.예를 들어 PersonId 객체의 구현은 다음과 같이 보일 수 있습니다here.
public readonly struct PersonId : IComparable<PersonId>, IEquatable<PersonId>
{
public string Value { get; }
public PersonId(string value)
{
Value = value;
}
public static PersonId New() => new PersonId(Guid.NewGuid().ToString());
public bool Equals(PersonId other) => this.Value.Equals(other.Value);
public int CompareTo(PersonId other) => Value.CompareTo(other.Value);
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
return obj is PersonId other && Equals(other);
}
public override int GetHashCode() => Value.GetHashCode();
public override string ToString() => Value.ToString();
public static bool operator ==(PersonId a, PersonId b) => a.CompareTo(b) == 0;
public static bool operator !=(PersonId a, PersonId b) => !(a == b);
}
public class Person
{
public Person(PersonId id, string firstName, string lastName, Address address)
{
// initialisation logic
}
public PersonId Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
}
이것은 매우 좋다. 왜냐하면 Person 클래스는 현재 자신의 PersonId를 ID로 사용하기 때문이다. 이것은 의외로 다른 유형의 ID로 사용할 수 없다. 왜냐하면 그것은 자신의 강한 유형의 ID를 가지고 있기 때문이다.
그러나, 이 PersonId 정의가 좀 커서, 만들고자 하는 모든 강력한 ID에 대해 설명하기가 매우 번거롭다는 것을 알 수 있습니다.솔직히 이 장애는 C# 개발에서 여전히 강력한 유형 ID가 흔치 않은 원인일 수 있다.
다행히도 C#9에서 우리는 새로운 기록 유형을 가지게 되었고, 이로써 강력한 유형의 ID를 정의하는 것이 더욱 쉬워졌기 때문에, 그것의 사용이 더욱 보편화되기를 희망합니다. (기록에 관한 내용을 더 많이 읽을 수 있습니다. here
// PersonId as a record
public record PersonId(string Value);
// how to initialise
var personId = new PersonId("my-id");
네, 그렇습니다.이는 문자열 속성 이름이 Value인 PersonId 레코드를 선언하며 구조 함수를 통해 전달할 수 있습니다.레코드는 해당 속성의 값에 따라 자동으로 동일성을 설정하므로 선언에 다른 내용을 추가할 필요가 없습니다.
F의 오리지널 마니아 #
비록 본고는 주로 C#를 주목하고 위에서 응용한 모든 원칙을 F#에 사용할 수 있지만 나는 F#가 독특한 특성을 가지고 있어 주의할 필요가 있다고 생각한다.
차별 연합은 F#(C#이 아닌 여러 언어)의 데이터 유형으로 상황에 따라 서로 다른 유형의 데이터를 되돌려받을 수 있다(차별 연합에 대한 자세한 정보는 참조here.흔히 볼 수 있는 예는 오류 처리입니다.
type Result<'a> =
| Data of 'a
| Error of string
위의 예시에서 함수가 일반적인 데이터 형식을 되돌려줄 수 있지만, 오류가 발생하면 문자열을 되돌려줍니다.
그러나 대소문자를 구분하는 연합은 기본 유형의 포장기를 충당하고 함수에 유형 안전성을 제공할 수 있다.예를 들어 다음과 같은 개인 기록이 있을 수 있습니다.
type Person = {
FirstName: string;
LastName: string;
EmailAddress: string;
}
문제는 전자메일 주소가 사실상 하나의 문자열이 아니라 특정한 형식이 있기 때문에 우리는 이를 위해 특정한 검증 논리를 설계해야 할 수도 있다는 것이다.따라서 자신의 유형에 봉인하는 것이 좋다.노조를 일례로 차별하는 것은 정말 쉽다.
type EmailAddress = EmailAddress of string
type Person = {
FirstName: string;
LastName: string;
EmailAddres: EmailAddress;
}
이제 Person 레코드는 EmailAddress 유형의 e-메일 주소만 받습니다.
결론
이 글에서 나는 원시적인 괴로움의 개념을 소개했다. 그것이 어떤 문제를 초래할 수 있는지, 그리고 그것을 어떻게 해결할 수 있는지.정보를 가져가서 자신의 코드 라이브러리에서 사용해서 더욱 안전하고 유지보수가 가능한 코드를 만들 수 있기를 바랍니다.
나의 게시물은 주로 무더기에 관한 것이다.NET 및 Vue 네트워크 개발 (곧 더 많은 F# 컨텐츠가 있을 수 있음!)어떤 댓글도 놓치지 않도록 본 블로그와subscribe to my newsletter를 주목해 주십시오.만약 당신이 이 문장이 매우 유용하다고 생각한다면, 좋아하고 공유해 주십시오.너도 인터넷에서 나를 찾을 수 있다.
Reference
이 문제에 관하여(원시 미혹증의 치료 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/dr_sam_walpole/a-cure-for-primitive-obsession-14l6
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
public class Person
{
public Person(string id, string firstName, string lastName, string address, string postcode, string city, string country)
{
// initialisation logic
}
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string PostCode { get; set; }
public string City { get; set; }
public string Country { get; set; }
public void ChangeAddress(string address, string postcode, string city, string country)
{
// change address logic
}
}
public class Address
{
public Address(string address, string postCode, string city, string country)
{
// initialisation logic
}
public string Address { get; set; }
public string PostCode { get; set; }
public string City { get; set; }
public string Country { get; set; }
}
public class Person
{
public Person(string id, string firstName, string lastName, Address address)
{
// initialisation logic
}
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
}
public readonly struct PersonId : IComparable<PersonId>, IEquatable<PersonId>
{
public string Value { get; }
public PersonId(string value)
{
Value = value;
}
public static PersonId New() => new PersonId(Guid.NewGuid().ToString());
public bool Equals(PersonId other) => this.Value.Equals(other.Value);
public int CompareTo(PersonId other) => Value.CompareTo(other.Value);
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
return obj is PersonId other && Equals(other);
}
public override int GetHashCode() => Value.GetHashCode();
public override string ToString() => Value.ToString();
public static bool operator ==(PersonId a, PersonId b) => a.CompareTo(b) == 0;
public static bool operator !=(PersonId a, PersonId b) => !(a == b);
}
public class Person
{
public Person(PersonId id, string firstName, string lastName, Address address)
{
// initialisation logic
}
public PersonId Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
}
// PersonId as a record
public record PersonId(string Value);
// how to initialise
var personId = new PersonId("my-id");
비록 본고는 주로 C#를 주목하고 위에서 응용한 모든 원칙을 F#에 사용할 수 있지만 나는 F#가 독특한 특성을 가지고 있어 주의할 필요가 있다고 생각한다.
차별 연합은 F#(C#이 아닌 여러 언어)의 데이터 유형으로 상황에 따라 서로 다른 유형의 데이터를 되돌려받을 수 있다(차별 연합에 대한 자세한 정보는 참조here.흔히 볼 수 있는 예는 오류 처리입니다.
type Result<'a> =
| Data of 'a
| Error of string
위의 예시에서 함수가 일반적인 데이터 형식을 되돌려줄 수 있지만, 오류가 발생하면 문자열을 되돌려줍니다.그러나 대소문자를 구분하는 연합은 기본 유형의 포장기를 충당하고 함수에 유형 안전성을 제공할 수 있다.예를 들어 다음과 같은 개인 기록이 있을 수 있습니다.
type Person = {
FirstName: string;
LastName: string;
EmailAddress: string;
}
문제는 전자메일 주소가 사실상 하나의 문자열이 아니라 특정한 형식이 있기 때문에 우리는 이를 위해 특정한 검증 논리를 설계해야 할 수도 있다는 것이다.따라서 자신의 유형에 봉인하는 것이 좋다.노조를 일례로 차별하는 것은 정말 쉽다.type EmailAddress = EmailAddress of string
type Person = {
FirstName: string;
LastName: string;
EmailAddres: EmailAddress;
}
이제 Person 레코드는 EmailAddress 유형의 e-메일 주소만 받습니다.결론
이 글에서 나는 원시적인 괴로움의 개념을 소개했다. 그것이 어떤 문제를 초래할 수 있는지, 그리고 그것을 어떻게 해결할 수 있는지.정보를 가져가서 자신의 코드 라이브러리에서 사용해서 더욱 안전하고 유지보수가 가능한 코드를 만들 수 있기를 바랍니다.
나의 게시물은 주로 무더기에 관한 것이다.NET 및 Vue 네트워크 개발 (곧 더 많은 F# 컨텐츠가 있을 수 있음!)어떤 댓글도 놓치지 않도록 본 블로그와subscribe to my newsletter를 주목해 주십시오.만약 당신이 이 문장이 매우 유용하다고 생각한다면, 좋아하고 공유해 주십시오.너도 인터넷에서 나를 찾을 수 있다.
Reference
이 문제에 관하여(원시 미혹증의 치료 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/dr_sam_walpole/a-cure-for-primitive-obsession-14l6
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(원시 미혹증의 치료 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/dr_sam_walpole/a-cure-for-primitive-obsession-14l6텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)