728x90
728x90
728x90

HowTo_Programming-201805.pdf


올해 5월에 나온 자료다... 한번쯤은 읽어보고, 모르는 단어나 용어가 있으면 찾아서 읽어보면 좋을 것 같다.

728x90
728x90

쭉 읽어보니.. 너무 많은 듯 하여 요약 시킬 필요성을 느꼇다...

간단하게 요약만 하겠다. 본문(https://google.github.io/styleguide/cppguide.html#Nonstandard_Extensions) 참조할 것

 

모든 내용이 있는 것은 아니다... 잘 모르겠는 부분 또는 필요없어 보이는 부분은 넘어갔다.

 

 

- Header Guard를 할 것. (#pragma once, #ifdef...)

 

- Template, inline은 Header파일에 선언과 정의를 같이 넣을 것.

 

- Header파일에는 필요한 Header파일을 모두 include 할 것.

 

- Header Guard는 Project_Path_File_H 형식으로 만들어야 한다.

foo/src/bar/bar.z 파일의 경우 아래와 같이 작성한다.

#ifndef FOO_BAR_BAZ_H_ #define FOO_BAR_BAZ_H_  ...  #endif  // FOO_BAR_BAZ_H_

 

- forward declarations를 사용하지 말자.

#include <iostream>  int add(int x, int y); // forward declaration using function prototype  int main() {     using namespace std;     cout << "The sum of 3 and 4 is " << add(3, 4) << endl;     return 0; }
int add(int x, int y) {     return x + y; }

 

- inline function 은 함수의 길이가 10줄 이하일 때만 사용하자.

 

- include의 이름과 순서는 다음과 같이 한다.

공통 헤더, C 라이브러리, C++ 라이브러리, 다른 라이브러리의 Header, 프로젝트의 Header

 

- namespace는 몇몇 상황을 제외하고 사용하자. (using namespace 는 사용을 자제하자.)

 

- global 변수는 사용하지말 것, namespace 내부에 Nonmember 변수를 배치할 것, 단순히 static 함수를 그룹화하기 위해 클래스를 사용하지 말 것.

 

- 지역 변수의 경우 선언과 동시에 초기화를 할 것.

int i; i = f();      // Bad -- initialization separate from declaration. 
int j = g();  // Good -- declaration has initialization. 
std::vector<int> v; v.push_back(1);  // Prefer initializing using brace initialization. v.push_back(2); 
std::vector<int> v = {1, 2};  // Good -- v starts initialized.

 

- smart pointer(unique_ptr, share_ptr) 사용 금지.

 

- 생성자에서 virtual function 호출을 피하고 실패할 수 있는 초기화를 피할 것.

 

- 암묵적 형변환을 사용하지 말고 명시적 형변환을 사용하자.

 

- struct와 class를 분리해서 사용하고, struct는 데이터를 전달하는 passive object에만 사용할 것.

 

- class의 멤버 정의는 public, protected, private 순서로 정의해야 된다.

 

- 매개 변수를 이용한 출력보다는 return 값을 이용하자.

 

- 하나의 함수는 길이가 40줄이 넘지 않게 구현하자.

 

- RTTI 사용하지 말자.

 

- 사용해야할 때마다 const를 사용하고, c++11에서는 constexpr이 더 낫다.

 

- Preprocessor Macros를 Header에 선언하지말자. inline, enum, const 등을 더 사용하자.

 

- 정수는 0, 실수는 0.0, 포인터는 nullptr, 문자는 '\n'를 사용하자.

 

- sizeof(type)를 사용할때에는 type은 변수명을 사용하자.

Struct data; memset(&data, 0, sizeof(data)); 
memset(&data, 0, sizeof(Struct));

 

- auto를 남발하지말자.

 

- Lambda

  • Use lambda expressions where appropriate, with formatting as described below.
  • Prefer explicit captures if the lambda may escape the current scope. For example, instead of:
    {   Foo foo;   ...   executor->Schedule([&] { Frobnicate(foo); })   ... } // BAD! The fact that the lambda makes use of a reference to `foo` and // possibly `this` (if `Frobnicate` is a member function) may not be // apparent on a cursory inspection. If the lambda is invoked after // the function returns, that would be bad, because both `foo` // and the enclosing object could have been destroyed. 
    prefer to write:
    {   Foo foo;   ...   executor->Schedule([&foo] { Frobnicate(foo); })   ... } // BETTER - The compile will fail if `Frobnicate` is a member // function, and it's clearer that `foo` is dangerously captured by // reference.

 

- 복잡한 Template Metaprogramming은 피하자.

 

- Boost 라이브러리를 사용할 때에는 승인된 라이브러리만 사용하자.

 

- 적절한 경우에만 C++11을 사용해야하고, 프로젝트에서 C++11 기능을 사용하기 전에 다른 환경으로의 이식성도 고려해야한다.

 

- 일반 이름 지정 규칙

이름은 설명이 있어야한다. 약어를 피하자. wikipedia 목록에 있는 약어 정도는 괜찮다.

int price_count_reader;    // No abbreviation. int num_errors;            // "num" is a widespread convention. int num_dns_connections;   // Most people know what "DNS" stands for. int lstm_size;             // "LSTM" is a common machine learning abbreviation. 
int n;                     // Meaningless. int nerr;                  // Ambiguous abbreviation. int n_comp_conns;          // Ambiguous abbreviation. int wgc_connections;       // Only your group knows what this stands for. int pc_reader;             // Lots of things can be abbreviated "pc". int cstmr_id;              // Deletes internal letters. FooBarRequestInfo fbri;    // Not even a word.

 

- Type Names

Type names start with a capital letter and have a capital letter for each new word, with no underscores: MyExcitingClass, MyExcitingEnum.

The names of all types — classes, structs, type aliases, enums, and type template parameters — have the same naming convention. Type names should start with a capital letter and have a capital letter for each new word. No underscores. For example:

// classes and structs class UrlTable { ... class UrlTableTester { ... struct UrlTableProperties { ...  // typedefs typedef hash_map<UrlTableProperties *, string> PropertiesMap;  // using aliases using PropertiesMap = hash_map<UrlTableProperties *, string>;  // enums enum UrlTableErrors { ...

 

- Variable Names

변수의 이름 (함수, 매개 변수 포함) 및 데이터 멤버는 모두 소문자로 시작하며 다너 사이에 밑줄이 있을 수 있다. 클래스의 데이터 멤버 변수에는 마지막에 밑줄을 넣는다.

Common Variable names

For example:

string table_name;  // OK - uses underscore. string tablename;   // OK - all lowercase. 
string tableName;   // Bad - mixed case.

 

클래스

Data members of classes, both static and non-static, are named like ordinary nonmember variables, but with a trailing underscore.

class TableInfo {   ...  private:   string table_name_;  // OK - underscore at end.   string tablename_;   // OK.   static Pool<TableInfo>* pool_;  // OK. };

 

구조체

Data members of structs, both static and non-static, are named like ordinary nonmember variables. They do not have the trailing underscores that data members in classes have.

struct UrlTableProperties {   string name;   int num_entries;   static Pool<UrlTableProperties>* pool; }; 

See Structs vs. Classes for a discussion of when to use a struct versus a class.

 

Const

Variables declared constexpr or const, and whose value is fixed for the duration of the program, are named with a leading "k" followed by mixed case. Underscores can be used as separators in the rare cases where capitalization cannot be used for separation. For example:

const int kDaysInAWeek = 7; const int kAndroid8_0_0 = 24;  // Android 8.0.0 

All such variables with static storage duration (i.e. statics and globals, see Storage Duration for details) should be named this way. This convention is optional for variables of other storage classes, e.g. automatic variables, otherwise the usual variable naming rules apply.

 

함수 이름

Regular functions have mixed case; accessors and mutators may be named like variables.

Ordinarily, functions should start with a capital letter and have a capital letter for each new word.

AddTableEntry() DeleteUrl() OpenFileOrDie() 

(The same naming rule applies to class- and namespace-scope constants that are exposed as part of an API and that are intended to look like functions, because the fact that they're objects rather than functions is an unimportant implementation detail.)

Accessors and mutators (get and set functions) may be named like variables. These often correspond to actual member variables, but this is not required. For example, int count() and void set_count(int count).

 

네임스페이스 이름은 모두 소문자로 한다.

 

Enumerators

Enumerators (for both scoped and unscoped enums) should be named either like constants or like macros: either kEnumName or ENUM_NAME.
Preferably, the individual enumerators should be named like constants. However, it is also acceptable to name them like macros. The enumeration name, UrlTableErrors (and AlternateUrlTableErrors), is a type, and therefore mixed case.
enum UrlTableErrors {  kOK = 0,  kErrorOutOfMemory,  kErrorMalformedInput,};enum AlternateUrlTableErrors {  OK = 0,  OUT_OF_MEMORY = 1,  MALFORMED_INPUT = 2,};

 

매크로 이름

일반 적으로는 매크로는 사용하지 않아야한다. 하지만 사용해야 한다면 모든 글자는 대문자와 밑줄로 지정해야 한다.

#define ROUND(x) ... #define PI_ROUNDED 3.0

 

- 주석 // 또는 /* */ 중에서 //을 더 많이 사용하도록 하자.

 

- 코드 한줄당 80자를 초과하지 말자.

 

- ASCII 보다는 UTF-8을 사용하자.

 

- Tab보다는 Spacebar를 사용하자.

 

- 조건부

Prefer no spaces inside parentheses. The if and else keywords belong on separate lines.

There are two acceptable formats for a basic conditional statement. One includes spaces between the parentheses and the condition, and one does not.

The most common form is without spaces. Either is fine, but be consistent. If you are modifying a file, use the format that is already present. If you are writing new code, use the format that the other files in that directory or project use. If in doubt and you have no personal preference, do not add the spaces.

if (condition) {  // no spaces inside parentheses   ...  // 2 space indent. } else if (...) {  // The else goes on the same line as the closing brace.   ... } else {   ... } 

If you prefer you may add spaces inside the parentheses:

if ( condition ) {  // spaces inside parentheses - rare   ...  // 2 space indent. } else {  // The else goes on the same line as the closing brace.   ... } 

Note that in all cases you must have a space between the if and the open parenthesis. You must also have a space between the close parenthesis and the curly brace, if you're using one.

if(condition) {   // Bad - space missing after IF. if (condition){   // Bad - space missing before {. if(condition){    // Doubly bad. 
if (condition) {  // Good - proper space after IF and before {. 

Short conditional statements may be written on one line if this enhances readability. You may use this only when the line is brief and the statement does not use the else clause.

if (x == kFoo) return new Foo(); if (x == kBar) return new Bar(); 

This is not allowed when the if statement has an else:

// Not allowed - IF statement on one line when there is an ELSE clause if (x) DoThis(); else DoThat(); 

In general, curly braces are not required for single-line statements, but they are allowed if you like them; conditional or loop statements with complex conditions or statements may be more readable with curly braces. Some projects require that an if must always have an accompanying brace.

if (condition)   DoSomething();  // 2 space indent.  if (condition) {   DoSomething();  // 2 space indent. } 

However, if one part of an if-else statement uses curly braces, the other part must too:

// Not allowed - curly on IF but not ELSE if (condition) {   foo; } else   bar;  // Not allowed - curly on ELSE but not IF if (condition)   foo; else {   bar; } 
// Curly braces around both IF and ELSE required because // one of the clauses used braces. if (condition) {   foo; } else {   bar; }

 

728x90
728x90
728x90
728x90

나의 경우 회사에서 개발할 때에는 항상 워터폴(Waterfall) 방법론이었다.


워터폴 방법론은 다음과 같다.



사실 고객은 자기가 원하는 것을 스스로도 정확하게 알지 못한다. 그냥 이런 기능이 있으면 좋겠는데, 저런 기능이 있으면 좋겠는데 할 뿐이다....


그렇기 때문에 처음부터 고객의 요구조건에 맞춰서 개발하다보면 계속해서 추가 요구 사항이 들어오게되고, 그러다보니 점점 구조가 꼬이는 형태가 될 수 밖에 없었다. (내가 근무한 방위산업체쪽에서는 항상 이랬다 ㅎㅎㅎㅎ)


즉, 이 워터폴 방식은 정말 제대로된 관리자가 고객의 요구를 정확하게 알고, 완벽한 설계를 하고, 완벽한 구현을 한 후 개발 완료를 할 때에는 좋은 개발 방법이지만, 그게 아니라면 좋지 못한 방법론이다. (보통 개발을 모르는 사람이 관리자였다...)




위의 문제 때문에 새롭게 나온 개발 방법론이 바로 애자일 모델(Agile Model) 이다.


사전에서 먼저 찾아보면 "Agile = 기민한, 날렵한" 이란 뜻이다.

즉 좋은 것을 빠르게 취하고, 낭비 없게 만드는 다양한 방법론을 통칭해 일컫는 말이다.


애자일 모델이 다른 방법론과 구별되는 가장 큰 차이점은 Less Document-Oriented, 즉 문서를 통한 개발이 아니라 Code-Oriented 실질적인 코딩을 통한 방법론이라는 것이다.



애자일 모델은 일정한 주기를 가지고 계속해서 프로토 타입(Proto Type)을 만들어서 고객에게 보여주며 고객과의 소통을 통한 요구사항을 추가하거나, 필요없는 부분은 제거하면서 점점 프로그램을 개발해 나가는 방법이다.


이렇게 실질적인 프로토 타입을 계속해서 만들어내는 과정에서 고객이 자연스럽게 참여할 수 있게 되고, 수정 요청을 하거나 다음 단계로 넘어가는 과정을 고객과 긴밀한 관계를 형성할 수 있다.




애자일 방식은 일반적으로 스크럼 프로세스를 따르게 되는데, 스크럼은 보통 30일 단위로 주기를 나누고, 짧게는 1~2주 길게는 3~4주 단위의 스프린트(개발 주기)로 쪼개서 개발하게 된다.


특정 기간 동안 해야 할 목표와 필요 작업을 명시하고, 실제로 어떻게 진행 되었는지 백로그(Backlog)를 남겨 각 스프린트가 끝나는 시점에 함께 모여 리뷰하고 피드백을 주고 받는 형태의 업무를 진행한다.


출처 : http://blog.rightbrain.co.kr/?p=5810

728x90

+ Recent posts