파일에서 설정을로드하고 저장하는 위치는 어디입니까?


9

이 질문은 파일에서 설정을로드하는 대부분의 프로그램에 적용되어야한다고 생각합니다. 내 질문은 프로그래밍 관점에서 왔으며 실제로 다른 클래스와 접근성 측면에서 파일의 설정로드를 처리하는 방법입니다. 예를 들어 :

  • 프로그램에 간단한 settings.ini파일 이 있다면 그 내용을 load()클래스 의 메소드 또는 생성자에 로드해야 합니까?
  • 값을 public static변수에 저장해야합니까 , 아니면 static속성을 가져오고 설정하는 방법이 있습니까?
  • 파일이 없거나 읽을 수없는 경우 어떻게됩니까? 나머지 프로그램에 해당 속성을 얻을 수 없다는 것을 어떻게 알 수 있습니까?
  • 기타

나는 여기에 올바른 장소에서 이것을 요구하기를 바라고 있습니다. 가능한 한 언어에 무관심한 질문을하고 싶었지만 상속과 같은 언어, 특히 Java 및 C # .NET에 주로 중점을 둡니다.


1
.NET의 경우, App.config 및 System.Configuration.ConfigurationManager 클래스를 사용하여 설정을 얻는 것이 가장 좋습니다.
— Gibson

@Gibson 방금 .NET에서 시작하고 있으므로 해당 수업에 대한 좋은 자습서로 나를 연결할 수 있습니까?
— Andy

Stackoverflow에는 많은 답변이 있습니다. 빠른 검색 결과 : stackoverflow.com/questions/114527/… 및 stackoverflow.com/questions/13043530/… MSDN에 대한 많은 정보가 여기에서 시작됩니다. msdn.microsoft.com/en-us/library/ms228063(v = vs.100) .aspx 및 msdn.microsoft.com/en-us/library/ms184658(v=vs.110).aspx
— Gibson

@Gibson 해당 링크에 감사드립니다. 그들은 매우 유용 할 것입니다.
— Andy

답변:


8

이것은 실제로 매우 중요한 질문이며 거의 모든 응용 프로그램의 핵심 부분이지만 충분한 중요성을 부여받지 못하기 때문에 종종 잘못 수행됩니다. 내 지침은 다음과 같습니다.

모든 설정을 포함하는 구성 클래스는 평범한 오래된 데이터 유형 struct / class이어야합니다.

class Config {
    int prop1;
    float prop2;
    SubConfig subConfig;
}

메소드를 가질 필요는 없으며 상속을 포함해서는 안됩니다 (변형 필드를 구현하기 위해 귀하의 언어로 유일하게 선택하지 않는 한-다음 단락 참조). 구성을 사용하여 설정을 더 작은 특정 구성 클래스 (예 : 위의 subConfig)로 그룹화 할 수 있습니다. 이 방법을 사용하면 최소한의 종속성이 있으므로 단위 테스트 및 응용 프로그램에서 전달하는 것이 이상적입니다.

다른 설정에 대한 구성이 구조가 다른 경우 변형 유형을 사용해야 할 수 있습니다. 올바른 (하위) 구성 클래스로 캐스트하기 위해 값을 읽을 때 특정 시점에 동적 캐스트를 넣어야한다는 것은 인정되며, 이는 다른 구성 설정에 따라 달라집니다.

다음을 수행하여 모든 설정을 필드로 입력하는 것에 대해 게으르지 않아야합니다.

class Config {
    Dictionary<string, string> values;
};

다루고있는 필드를 알 필요가없는 일반화 된 직렬화 클래스를 작성할 수 있다는 의미에서 유혹적입니다. 그러나 잘못되어 잠시 이유를 설명하겠습니다.

구성의 직렬화는 완전히 별도의 클래스에서 수행됩니다. 이 작업을 수행하는 데 사용하는 API 또는 라이브러리에 관계없이 직렬화 함수의 본문에는 기본적으로 파일의 경로 / 키에서 객체의 필드로의 맵에 해당하는 항목이 포함되어야합니다. 일부 언어는 좋은 내성을 제공하며 즉시 사용할 수 있으며, 다른 언어는 매핑을 명시 적으로 작성해야하지만 중요한 것은 매핑을 한 번만 작성하면됩니다. 예를 들어 c ++ 부스트 프로그램 옵션 파서 문서에서 수정 한이 추출을 고려하십시오.

struct Config {
   int opt;
} conf;
po::options_description desc("Allowed options");
desc.add_options()
    ("optimization", po::value<int>(&conf.opt)->default_value(10);

마지막 줄에는 기본적으로 "최적화"가 Config :: opt에 매핑되고 예상되는 형식의 선언이 있습니다. 파일의 매개 변수가 실제로 float 또는 int가 아니거나 존재하지 않는 경우 유형이 예상 한 것이 아닌 경우 구성 읽기가 실패하려고합니다. 즉, 파일 형식 / 확인에 문제가 있기 때문에 파일을 읽을 때 오류가 발생해야하며 예외 / 반환 코드를 던져 정확한 문제를보고해야합니다. 나중에 프로그램에서 이것을 지연 시켜서는 안됩니다. 그렇기 때문에 파일을 읽을 때 실패하지 않는 위에서 언급 한대로 모든 사전 스타일 구성 요소를 잡으려는 유혹을받지 않아야합니다. 값이 필요할 때까지 캐스팅이 지연됩니다.

Config 클래스는 어떤 방식 으로든 읽기 전용으로 만들어야합니다. 클래스를 작성할 때 클래스의 컨텐츠를 한 번 설정하고 파일에서 초기화해야합니다. 변경되지 않는 const 설정뿐만 아니라 변경되는 응용 프로그램에서 동적 설정이 필요한 경우 구성 클래스의 비트가 읽기 전용이 아닌 동적 클래스를 처리하는 별도의 클래스가 있어야합니다 .

프로그램의 한 위치에서 파일을 읽는 것이 이상적입니다. 즉, " ConfigReader" 인스턴스가 하나만 있습니다 . 그러나 Config 인스턴스를 필요한 곳으로 전달하는 데 어려움을 겪고 있다면 전역 구성을 도입하는 것보다 두 번째 ConfigReader를 사용하는 것이 좋습니다 (이것은 OP가 의미하는 것입니다 "정적" "), 다음으로 넘어갑니다.

싱글 톤의 매혹적인 사이렌 노래를 피하십시오. "클래스 클래스를 통과해야하는 것을 막아 줄 것입니다. 모든 생성자는 아름답고 깨끗합니다. 계속해보세요." 진실은 잘 설계된 테스트 가능한 아키텍처로 구성 클래스 또는 그 일부를 응용 프로그램의 많은 클래스를 통해 전달할 필요가 거의 없습니다. 최상위 클래스, main () 함수 또는 무엇이든 찾을 수있는 것은 개별 값으로 conf를 풀고 구성 요소 클래스에 인수로 제공 한 인수 (수동 종속성) 주입). 싱글 톤 / 글로벌 / 정적 conf는 애플리케이션 테스트를 구현하고 이해하기 훨씬 어렵게 만듭니다. 예를 들어, 새로운 개발자가 팀을 구성하기 위해 글로벌 상태를 설정해야한다는 것을 모르는 새로운 개발자를 혼란스럽게 할 것입니다.

언어가 속성을 지원하는 경우 이러한 목적으로 사용해야합니다. 그 이유는 하나 이상의 다른 설정에 따라 파생 된 구성 설정을 매우 쉽게 추가 할 수 있기 때문입니다. 예 :

int Prop1 { get; }
int Prop2 { get; }
int Prop3 { get { return Prop1*Prop2; }

언어가 속성 관용구를 기본적으로 지원하지 않는 경우 동일한 효과를 얻는 해결 방법이 있거나 보너스 설정을 제공하는 래퍼 클래스를 만들면됩니다. 그렇지 않으면 속성의 이점을 부여 할 수 없다면 수동으로 작성하고 일부 OO 신을 기쁘게하기 위해 게터 / 세터를 사용하는 것이 시간 낭비입니다. 평범한 낡은 밭에서 더 나아질 것입니다.

우선 순위에 따라 서로 다른 위치에서 여러 구성을 병합하고 가져 오는 시스템이 필요할 수 있습니다. 우선 순위는 잘 정의되어 있고 모든 개발자 / 사용자가 이해해야합니다 (예 : Windows 레지스트리 HKEY_CURRENT_USER / HKEY_LOCAL_MACHINE 고려). 이 기능 스타일을 수행하여 구성을 읽기 전용으로 유지할 수 있습니다.

final_conf = merge(user_conf, machine_conf)

오히려

conf.update(user_conf)

선택한 프레임 워크 / 언어가 자체적으로 잘 알려진 기본 제공 구성 메커니즘을 제공하는 경우 자신의 롤링 대신이를 사용하는 이점을 고려해야합니다.

그래서. 고려해야 할 많은 측면-올바르게 이해하면 응용 프로그램 아키텍처에 크게 영향을 미쳐 버그를 줄이며 쉽게 테스트 할 수 있으며 다른 곳에서 좋은 디자인을 사용해야합니다.


+1 답변 주셔서 감사합니다. 이전에는 사용자 설정을 저장했을 때 .ini사람이 읽을 수 있도록 파일에서 방금 읽었 지만 변수가있는 클래스를 직렬화해야한다고 제안합니까?
— Andy

.ini는 구문 분석이 쉽고 .ini를 가능한 형식으로 포함하는 많은 API가 있습니다. 텍스트 파싱의 거친 작업을 돕기 위해 이러한 API를 사용하는 것이 좋지만 최종 결과는 POD 클래스를 초기화 한 것입니다. 클래스의 필드에서 어떤 형식으로 복사하거나 읽는 일반적인 의미로 직렬화라는 용어를 사용합니다. 일반적으로 java.io.Serializable에 대해 이해되는 것처럼 이진에 클래스를 직접 직렬화하는 더 구체적인 정의는 아닙니다. ).
— 베네딕트

이제는 조금 더 잘 이해합니다. 따라서 본질적으로 모든 필드 / 설정이있는 하나의 클래스가 있고 파일에서 해당 클래스의 값을 설정하는 클래스가 있습니까? 그렇다면 다른 클래스의 첫 번째 클래스에서 값을 어떻게 가져 옵니까?
— Andy

사례별로. 최상위 클래스 중 일부는 너무 많은 매개 변수에 의존하는 경우 전달 된 전체 구성 인스턴스에 대한 참조가 필요할 수 있습니다. 다른 클래스는 하나 또는 두 개의 매개 변수 만 필요할 수도 있지만 Config 개체에 이들을 연결할 필요는 없습니다 (테스트하기 쉽도록). 몇 개의 매개 변수를 응용 프로그램을 통해 전달하십시오. 내 대답에서 언급했듯이 테스트 가능 / DI 지향 아키텍처로 빌드하면 필요한 값을 얻는 것이 일반적으로 어렵지 않습니다. 위험에 처한 글로벌 액세스를 사용하십시오.
— 베네딕트

그렇다면 상속이 필요하지 않은 경우 구성 객체가 클래스로 전달되도록 제안하는 방법은 무엇입니까? 생성자를 통해? 따라서 프로그램의 주요 메소드에서 Config 클래스에 값을 저장하는 리더 클래스가 시작된 다음 주 메소드가 Config 객체 또는 개별 변수를 다른 클래스로 전달합니까?
— Andy

4

일반적으로 (제 생각에) 응용 프로그램에서 구성 저장 방법을 처리하고 구성을 모듈에 전달하는 것이 가장 좋습니다. 이것은 파일이나 웹 서비스 또는 데이터베이스를 대상으로 할 수 있도록 설정을 저장 하는 방법에 유연성을 허용합니다 ...

또한 응용 프로그램에 "사고가 발생할 때 발생하는 상황"에 대한 부담을 가중시킵니다.이 장애는 해당 장애가 무엇을 의미하는지 잘 알고 있습니다.

또한 파일 시스템을 만지거나 정적 액세스로 인해 발생하는 동시성 문제를 처리하지 않고 구성 객체를 전달할 수있을 때 단위 테스트를보다 쉽게 ​​수행 할 수 있습니다.


답변 해 주셔서 감사합니다. 이해가되지 않습니다. 응용 프로그램을 작성할 때 이야기하고 있으므로 구성을 처리 할 것이 없으므로 프로그래머로서 실패의 의미를 알고 있습니다.
— Andy

@andy-물론 모듈이 구성에 직접 액세스하는 경우 작업중인 컨텍스트를 모르므로 구성 문제를 처리하는 방법을 결정할 수 없습니다. 응용 프로그램이로드를 수행하는 경우 컨텍스트를 알고 있기 때문에 모든 문제를 처리 할 수 ​​있습니다. 일부 앱은 기본값으로 장애 조치를 원하고 다른 일부는 중단하려는 경우 등
— Telastyn

여기서 명확히하기 위해 모듈별로 클래스 또는 프로그램의 실제 확장을 참조하고 있습니까? 코드 내부의 설정을 실제로 주 프로그램에 저장하는 가장 좋은 위치와 다른 클래스가 설정에 액세스하도록 허용하는 방법에 대해 문의하고 있기 때문입니다. 따라서 구성 파일을로드 한 다음 어딘가 / 어떻게 든 설정을 저장하여 파일을 계속 참조 할 필요가 없습니다.
— Andy

0

클래스를 프로그래밍하기 위해 .NET을 사용하는 경우 Resources, web.config 또는 사용자 정의 파일과 같은 다른 옵션이 있습니다.

Resources 또는 web.config를 사용하는 경우 데이터는 실제로 XML 파일로 저장되지만 로딩 속도가 더 빠릅니다.

이러한 파일에서 데이터를 검색하여 다른 위치에 저장하는 것은 기본적으로 메모리에로드되므로 메모리를 두 번 사용하는 것과 같습니다.

다른 파일이나 프로그래밍 언어의 경우 Benedict의 위 답변이 작동합니다.


답장을 보내 주셔서 감사합니다. 답변이 늦어 죄송합니다. Resources를 사용하는 것이 좋은 선택이지만, 다른 언어로 동일한 프로그램을 개발할 계획 인 것 같습니다. XML 또는 JSON 파일이 있지만 같은 파일을 다른 프로그래밍 언어로 읽을 수 있도록 내 수업에서 읽으십시오.
— Andy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.