현대 C를 작성하는 방법에 대해 일반적으로 인정되는 지침이 있습니까?


13

저는 강력한 Java / Groovy 배경을 가지고 있으며 관리 소프트웨어를 위해 상당히 큰 C 코드 기반을 유지 관리하는 팀에 배정되었습니다.

데이터베이스에서 얼룩을 처리하거나 PDF 및 Excel로 보고서를 생성하는 것과 같은 일부 문제점은 Java 웹 서비스로 외부화되었습니다.

그러나 Java 개발자로서 코드의 일부 측면에서 약간 혼란 스럽습니다.

  • 장황하다 (특히 '예외'를 ​​다룰 때)
  • 거대한 방법이 많이 있습니다 (많은 2000+ 라인 방법)
  • 고급 데이터 구조가 없습니다 (목록, 설정 및지도가 많이 누락되었습니다)
  • 걱정할 필요가 없습니다 (SQL은 코드 전체에서 즐겁게 혼합됩니다)

결과적으로 비즈니스가 수많은 기술 코드에 숨겨져 있고 Object Oriented와 기능적 프로그래밍으로 구성된 내 두뇌가 편안하지 않다고 생각합니다.

프로젝트의 장점은 코드가 간단하다는 것입니다. 프레임 워크, 런타임시 바이트 코드 조작, AOP가 없습니다. 그리고 서버는 자바가 "hello world"를 뱉을 때보 다 적은 메모리를 사용하여 단일 머신으로 10000 명 이상의 사용자에게 동시에 응답 할 수 있습니다.

일반적으로 받아 들여지는 현대 원칙에 따라 C 코드를 작성하는 방법을 배우고 싶습니다. 현대 C를 어떻게 작성하고 구조화해야하는지에 대해 일반적으로 인정되는 원칙이 있습니까?

'Effective Java'서적과 약간 비슷하지만 C에 해당합니다.

답변과 의견에 비추어 편집하십시오.

  • 내 사고 방식을 C 코드에 적용하고 OOP에 반영하려고하지 않습니다.
  • 주석 (GNU 코딩 표준 및 Linux 커널 코딩 스타일)에서 권장 코딩 스타일 가이드를 스캔하기 시작했습니다.
  • 그런 다음 동료에게이 코드 스타일을 제안하려고합니다. 가장 어려운 부분은 동료에게 큰 방법을 작은 부분으로 나눌 수 있고 동일한 4 줄의 오류 처리 코드를 반복하는 것이 방법의 도움으로 피할 수 있다는 것을 동료에게 확신시키는 것일 수 있습니다.

5
응용 프로그램이 실제로 현대화되어야합니까, 아니면 작성된 방식이 익숙하지 않기 때문에 그렇게 생각하십니까?
Blrfl


1
@Blrfl, 응용 프로그램이 오래된 표준으로 작성되었다고 생각합니다. 나는 (행정적) C의 오늘 (2016) 표준이 무엇인지 알고 싶습니다. 현재 앱을 리팩터링하거나 재구성하고 싶지 않습니다. 코드의 다음 부분을 어떻게 작성해야하는지 생각하고 싶습니다.
기 illa


3
@antlersoft : 2,000 개의 라인 함수는 여러 가지 간단한 일을 차례로 수행하는 데 전혀 문제가없고 변명 할 필요가 없습니다. "2,000 개의 라인 함수를 작성해서는 안되기 때문에 2,000 개의 라인 함수를 작성해서는 안됩니다"와 같은 순환 인수로 응답하지 마십시오.
gnasher729

답변:


14

귀하의 질문에서 코드가 오래된 C가 아니라 프로그래밍이 잘못 되었다는 문제가 있습니다. 자세한 내용, 2000 개 이상의 거대한 라인 기능 또는 관심사 분리와 같이 언급 한 대부분의 문제는 모든 언어, C 또는 Java에 적용 할 수 있습니다.

오류 처리와 관련하여 자세한 정보가 언급되었습니다. 예제를 제공하지 않았으므로 오류 처리 코드도 code 입니다. 상용구 코드의 반복적 인 섹션에 대한 변명은 없습니다. 그것을 밖으로 인수; 함수로 또는 (별도의 함수를 작성할 가치가없는 경우) goto Error;패턴을 수행 하고 오류 처리 및 자원 정리를 Error:함수 맨 아래 섹션으로 이동하십시오 .

콜 체인에 오류를 전달하는 것이 문제인 것 같으면 스스로에게 물어보십시오. 여기있는 함수가 실제로 문제가있는 작은 사람을 알아야합니까? 언어에 내장 된 예외 메커니즘을 사용하면 쉽게 처리 할 수 ​​있지만 일반적으로 오류 조건이 상위 코드의 논리를 오염시키지 않도록 예외를 조기에 처리하는 것이 좋습니다 (어떤 언어로든). 거기 함수가 있다면 정말 알 필요가에 방법이있다 에뮬레이션 예외setjmp하고 longjmp.

C와 관련된 유일한 문제는 표준 컨테이너가 없다는 것입니다. Set일반적으로 정렬 된 배열로 대체 할 수 있지만 Map(대부분의 경우) 페어 배열 또는 struct(키 세트를 알고 있다면 map[key] = value로 바뀝니다 s.key = value) 표준에 동적 배열 컨테이너가 없다는 사실 도서관. C99에서는 적어도 스택 ( int array[len]) 에 가변 길이 배열을 선언 할 수 있지만 len미리 계산해야하지만 (일반적으로 하드하지는 않음) 물론 스택 할당 객체로 반환 할 수는 없습니다. 대부분의 프로젝트는 자체 동적 배열 컨테이너를 작성하거나 오픈 소스 컨테이너를 채택합니다.

마지막으로, 내가 거기에 있음을 지적하고 싶습니다. 저는 C ++과 순수 C로 옮긴 Java 프로그래머였습니다. "좋은 C를 배우기 위해 책 X를 읽으십시오"라고 조언하고 싶지만 Java에 대한 것은 없습니다. 앞으로 나아가는 길은 언어와 표준 라이브러리의 모든 복잡성을 흡수하는 것입니다. C에서 생각하기 시작할 때까지 Google을 많이 읽고 많이 읽고 코드를 많이 작성하십시오. Java에서와 마찬가지로 C로 물건을 쓰려고 시도하는 것은 어머니가 직접 번역 한 단어로 외국어로 문장을 작성하는 것만큼이나 실망 스럽습니다. 혀; 당신과 독자 모두가 울부 짖습니다. 좋은 소식은 좋은 프로그래밍을 배우는 것은 느리지 만 다른 언어를 배우는 것은 빠르다는 것입니다. 자바로 괜찮은 코드를 작성한다면


1
대체로 이것은 정말 좋은 대답입니다. 나는 유효한 도구로 setjmp()/ 를 보는 것에 반대 할 것입니다 longjmp(): 그것은 심지어 정리를 시도하지 않습니다. 할당이 유출되고 보류 된 잠금이 해제되지 않고 열린 파일이 닫히지 않으며 일시적인 데이터 불일치가 영구적으로 유지됩니다. IMHO,이 기능 쌍은 기본적으로 발명 된 최악의 핵이며 구현이 가능하다는 전적으로 정당합니다. 결국 C에서 오류 처리를 수행하는 유효한 방법은 명시 적 오류 코드입니다.
cmaster-monica reinstate

@cmaster 예. 개인적 setjmp/longjmp으로 C에서 물에서 물고기가 나오는 것처럼 보였고 결코 사용하지 않았습니다. 인터넷상에서 예외를 흉내내는 수많은 튜토리얼 / 라이브러리 때문에 그것들을 포함시켜야한다는 느낌이 들었습니다. 그래서 실제로 그것을 사용하는 사람들이 있다고 생각했습니다.
올빼미 올빼미

7

프로젝트의 장점은 코드가 간단하다는 것입니다. 프레임 워크, 런타임시 바이트 코드 조작, AOP가 없습니다. 그리고 서버는 자바가 "hello world"를 뱉을 때보 다 적은 메모리를 사용하여 단일 머신으로 10000 명 이상의 사용자에게 동시에 응답 할 수 있습니다.

코드 복잡성이 낮고 성능이 우수한 소프트웨어를 "현대화"하는 데 리소스를 소비하는 데 시간과 가치가 있는지주의를 기울여야합니다. 새로운 버그를 직접 도입 할 가능성이 높은 것은 특히 익숙하지 않은 시스템 인 것 같습니다.

여전히 그 길을 가고 싶다면 다음을 제안합니다.

  • 소프트웨어 / 코드의 상태 다이어그램 만들기 (또는 생성)
  • 코드를 살펴보고 코드의 가장 복잡하거나 중요한 부분을 각각 목록으로 만듭니다.
  • 해당 코드베이스에 대해 잘 알고있는 사람을 찾아서 이런 방식으로 구축 된 이유와 문제를 일으키는 것으로 알려진 이유를 물어보십시오.
  • 배운 내용으로 문서 작성

이 시점에서 탐색 할 가치가 있는지 여부를 결정합니다. 회사의 문화가 실패에 대한 보상을하지 않는다면 상급 관리자 나 관리자로부터 녹색 불빛을 받으십시오.

  • 소프트웨어의 다른 빌딩 블록을 분류하고 각각에 대한 단위 테스트를 작성하십시오.
  • 다른 모듈을 서로 붙일 수있을 때까지 반복
  • 실제 사용자 상호 작용을 시뮬레이션하는 추가 테스트 수행 (스트레스 테스트 등)

나는 그것이 상당히 좋은 로드맵이라고 생각하며 필요한 곳으로 데려다 줄 것입니다. 이 프로젝트의 특성을 알지 못하면 많은 도움을주기가 어렵습니다. 면책 조항을 지나치게 경고하는 것으로 버리지 마십시오. 기존의 프로젝트를 자신이 선호하는 언어로 다시 작성하거나 "현대"도구를 사용하여 수많은 프로그래머가 먼지를 이겼습니다. 그것은 신중하게 생각해야 할 결정이며 관리 지원이나 동료의 도움 없이는 스스로 악의적으로 행동하지 말 것을 권한다.


2
나는 내 질문이 전혀 명확하지 않다는 것을 깨닫는다. 코드를 리팩터링하고 싶지 않습니다. 조금도. 기존 코드베이스를 그대로 유지하고 싶습니다. 그러나 새로운 기능을 위해 최신 C를 작성하는 방법을 배우고 싶습니다. 그리고 나는 여기에서 길을 잃었다. 내가 찾은 문서의 대부분은 'modern'C를 작성하는 방법이 아니라 C로 코딩하는 방법에 관한 것입니다. 아마도 'modern'C와 같은 것은 없을 것입니다.
Guillaume

1

더 높은 수준의 언어를 선호한다면 C 코드 나 Objective-C와 같이 C 코드와 매우 쉽게 혼합 될 수있는 언어가 있습니다.

또는 C와 C ++는 합리적으로 호환됩니다. 약간의 변경만으로 전체 코드베이스를 C ++로 컴파일 할 수 있습니다. 이름을 변경해야하는 "class"또는 "template"이라는 변수가 있지만 실제로는 전부입니다. (sizeof ( 'a')는 C와 C ++에서 다르지만, 내가 사용한 적이 없다고 생각합니다).

그 길을 가면 다음 관리자가 C ++에 너무 유창하지 않을 수도 있습니다. 멀리 가지 마십시오. C 프로그래머가 쉽게 이해할 수 있도록 C ++을 활용하십시오.


1
나는 여기에 동의하지 않아야한다. C와 C ++ 별개의 언어입니다 및 C ++ 컴파일러 (명시 적으로의 반환 값을 캐스팅에서 요구하는 몇 가지 코드 malloc)의 의미 C. 나쁜 관행을 고려 const하고 inline또한 매우 C와 C ++ 사이의 서로 다른, 그리고 물론 C의 ++ 이해하지 않습니다 __restrict. 두 언어로 컴파일되는 소스의 하위 집합에서도 언어를 서로 바꿔서 사용하지 마십시오.
문헌 : Angew는 더 이상 자랑 SO의없는

1

기본적으로 좋은 C 코드를 작성하는 것은 좋은 C ++ 또는 Java 코드를 작성하는 것과 같습니다 struct. 클래스를 원한다면을 사용하십시오 . 상속을 원하고 기본 struct을 이름없는 첫 번째 멤버로 포함하십시오 . 가상 함수를 원하고 정적 struct함수 포인터에 포인터를 추가하십시오 . 등등 등등. 그것은 C ++이 정확히 수행하는 것의 유일한 차이점입니다. 유일한 차이점은 C로 명시 적이라는 것입니다. 따라서 C에서 객체 지향 프로그래밍을 완벽하게 수행 할 수 있습니다. 하는 데 사용됩니다.

요점은 좋은 프로그래밍은 언어 기능이 아니라 패러다임에 관한 것입니다. 언어 기능이 사용하려는 패러다임을 제대로 지원할 수 있다면 항상 좋지만 언어 기능이 반드시 필요한 것은 아닙니다. 일단 이것을 깨닫고 나면 거의 모든 언어로 좋은 코드를 작성할 수 있습니다 (brainfuck 또는 INTERCAL과 같은 난해한 언어는 제외).

물론 표준 C 라이브러리에는 익숙한 멋진 컨테이너 클래스가 포함되어 있지 않습니다. 불행히도, 그것은 당신이 당신 자신을 사용하거나 동적으로 할당 된 배열을 사용 하여이 부족을 해결해야한다는 것을 의미합니다. 그러나 곧 당신이 알게 될 것입니다. 실제로 필요한 것은 동적 배열 ( malloc())과 클래스 내의 포인터 멤버를 통해 구현 된 연결된 목록 / 트리입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.