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


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) .aspxmsdn.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.