반응형



USS(Unique Set Size) : 프로세스만의 고유한 페이지 수. 공유되지 않는 프로세스에 private한 메모리 크기이다. 


PSS(Proportional Set Size) : USS + (공유 페이지 / 공유하는 프로세스 수). 즉, 프로세스 고유 메모리 사용량 + 하나의 프로세스가 차지하는 공유 메모리 비율이다. 만약 A프로세스가 6MB 메모리를 사용하고 그 중 2MB가 그 프로세스의 고유 영역이라면, 나머지 4MB는 공유 메모리이다. 4MB의 공유메모리를 4개의 프로세스가 공유하고 있다면 PSS는 2MB + (4MB/4) = 3MB가 된다.


 


[펌] http://ecogeo.tistory.com/255



'Linux' 카테고리의 다른 글

link error, undefined symbol  (0) 2017.03.28
open 되어있는 fd 확인하기.  (0) 2017.03.03
rpm 사용법  (0) 2014.02.13
Linux 커널 드라이버 모형: 협업의 장점 - in Beautiful code  (0) 2010.10.22
Linux kernel : NMI 감시기  (0) 2009.12.31
반응형

http://hardworkers.tistory.com/150


react 시작하기!!



http://nepi.tistory.com/entry/React-%EC%8B%9C%EC%9E%91



node js 튜토리얼....렁!!!


https://velopert.com/node-js-tutorials


 react , redux , express 등



https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript



db 는 mongo db




[Webpack]

web 성능개선을 위해 매우 중요!!!


https://webpack.js.org/

http://webpack.github.io/docs/node.js-api.html



webpack.config.js [configuration 파일]



- devtool : 개발환경 관련해서 설정하는 부분.!!!

   - 'source-map'  : bundle.js 등 으로 합쳐진 코드를 디버깅하기에는 무척 난해함, 

     개발할때 original source와 mapping 시켜서 디버깅 할 수 있도록 도와주는 툴


 ---- https://survivejs.com/webpack/building/source-maps/

--- 디버깅을 위해서는 source map이 중요합니다.!!!

- debug...



https://webpack.js.org/concepts/    : 컨셉 page 한눈에 알수 있음.ㅋ



디버깅 환경에서 실행하기.!!!



webpack.config.js 파일에


devtool:'source-map',

을 추가하기!!


npm run development



[김 땡땡]

어제 제가 redux-persist라고 redux 데이터 새로고침해도 유지되게 라이브러리 붙였는데요

window analyzer/system analyzer 등 모든화면에서 괜찮은데 

memo list에서 새로고침하면 lockup 비스무리하게 되더라구요

어제보다가 모르겠어서 말긴했는데;; 혹시 여유되시면 한번 봐주세요 

새로고침 안했을때는 잘 동작하는데 그화면에서 새로고침하면 bottom navigation이 안먹고 memo 추가하는것도 안되고 락업처럼 되더라구요 

redux-persist 적용되고 개발하기 완전 편해짐 



-----------------------------------------


[이 땡땡]

packsge.json 파일에서 build부분에 아래처럼 webpack 뒤에 --watch 붙이고


"build": "babel server --out-dir build --presets=es2015 && webpack --watch",


webpack.config.js 파일에서 plugins 내용을 기존꺼 대신


plugins:[

  new webpack.HotModuleReplacementPlugin()

]


이렇게 바꾸면 빌드속도가 20초에서 3초정도로 주는거같네요




-----------------------------------------------------


'Node.js , React, Docker' 카테고리의 다른 글

[React] Components  (0) 2024.09.07
[AWS] 여러가지 알아야 할것들  (3) 2024.07.12
Docker 간단히 이해하기  (0) 2024.07.11
[Docker] proxy 문제 해결  (0) 2021.11.11
REST API  (0) 2017.06.20
반응형


어떻게 compiler version 에 따라 API 지원 피쳐를 구분해서 제공할까 고민하다가 compiler 를 변경해가면서 직접 값을 정리해봤습니다.

예를 들면,

c++11 부터 지원하기 시작한 매우 유용한 feature들이 있습니다.

1. final, override keyword 

2. class 선언부에서 변수 초기화 하는것


이러다 보니, c++11로 개발하고 c++99 용 모듈에서도 사용할 수 있게 할 수 없을까?

하는 아이디어( 요구사항)이 있었습니다. 사실 개발은 c++11로 하고 싶었거든요.

아니면 code를 다시 다 걷어내거나 내부 로직에서 사용하고 있는 auto, lamda등을 다 걷어내야 하는 판국이라서 말이죠.


그래서 나온 아이디어가 이렇습니다.


1. 개발은 C++11로 한다.

2. 다른 모듈에는 header file 과 so( library)를 제공한다.

3. header file만 c++11과 c++99를 구분한다.

4. 모두 해피하다.!! ㅎㅎ


여기서 3번이 문제였는데요.

먼저 확인할 사항이 몇가지 있었습니다.

1. final, override keyword에 의해서 ABI 즉,  API 호환성이 달라지는가?

2. class 선언부에서 변수 초기화가 빠졌을때 이미 compile 된 so의 동작이 달라지는가?


이 두가지를 테스트 해봤습니다.

결과는 문제가 없더군요.


이렇게 해서 C++11로 개발하고 C++99용 header(? 사실 header file 내부에서 구분해서 처리) 를 제공할 수 있게 되었습니다.


물론, c++11의 lamda 를 interface로 사용한다거, auto 를 return 값이나 parameter로 사용한다거나(이건 c++14던가요?) 하는 부분은  API class들에서는 없애야 했습니다.




이 과정에서 조사했던 유용한 정보 하나 있습니다.

바로 gcc와 llvm 에 대해서  C++11 의 지원 feature 를 확인하기 위해서  predefine 되어있는 값들을 조사 한 것인데요.

아래와 같습니다.


조사해놓고 보니까 결국 , __cplusplus 만  확인하면 끝나는 것이었더라구요. ㅠ_ㅠ


gcc 4.6

__cplusplus int 1

__GNUC__ int 4

__GNUG__ int 4

__GXX_ABI_VERSION int 1002

__GNUC_MINOR__ int 6



gcc 4.9 

__cplusplus int 201103

__GNUC__ int 4

__GNUG__ int 4

__GXX_ABI_VERSION int 1002

__GNUC_MINOR__ int 9



llvm 4.6

__cplusplus int 201103

__GNUC__ int 4

__GNUG__ int 4

__GXX_ABI_VERSION int 1002

__GNUC_MINOR__ int 6

__clang__ int 1

__clang_major__ int 3

__clang_minor__ int 4



llvm 4.9

__cplusplus int 201103

__GNUC__ int 4

__GNUG__ int 4

__GXX_ABI_VERSION int 1002

__GNUC_MINOR__ int 9

__clang__ int 1

__clang_major__ int 3

__clang_minor__ int 6





반응형



evas_object_pass_events_set  --> 해당 오브잭트는 event를 안받음


evas_object_propagate_events_set  --> event를 받고 나서 부모(smart object)에게 보내는 동작


evas_object_repeat_events_set --> event를 좌표상으로 내 밑에 있는 object도 event를 보냄


'tizen' 카테고리의 다른 글

CLI (Command Line Inteface) 를 이용한 build  (0) 2015.11.30
tpk install, 설치  (0) 2014.05.28
Tizen::Content::ContentSearch 사용하기  (1) 2010.05.19
반응형




GCC 에서 지원하는 C++11 피쳐들을 알아보자.


gcc 4.9 에서는 c++11 피쳐가 지원된다는 것은 알고 있을겁니다.


그런데, gcc 4.6에서도  c++11 이 지원된다고 아셨다면, 아래 표를 참조해서 내가 쓸수 있는 피쳐와 그렇지 못한 피쳐를 확인해야 합니다.


gcc 4.6 부터 c++11 피쳐들이 100% 지원되는 것이 아니기 때문이죠.


대표적으로 유용한 override keyword 는 4.7 부터 지원하고 있죠.



<참고  : https://gcc.gnu.org/projects/cxx-status.html#cxx11>

Language FeatureProposalAvailable in GCC?SD-6 Feature Test
Rvalue referencesN2118GCC 4.3__cpp_rvalue_references >= 200610
    Rvalue references for *thisN2439GCC 4.8.1__cpp_ref_qualifiers >= 200710
Initialization of class objects by rvaluesN1610Yes
Non-static data member initializersN2756GCC 4.7__cpp_nsdmi >= 200809
Variadic templatesN2242GCC 4.3__cpp_variadic_templates >= 200704
    Extending variadic template template parametersN2555GCC 4.4
Initializer listsN2672GCC 4.4__cpp_initializer_lists >= 200806
Static assertionsN1720GCC 4.3__cpp_static_assert >= 200410
auto-typed variablesN1984GCC 4.4
    Multi-declarator autoN1737GCC 4.4
    Removal of auto as a storage-class specifierN2546GCC 4.4
    New function declarator syntaxN2541GCC 4.4
New wording for C++0x lambdasN2927GCC 4.5__cpp_lambdas >= 200907
Declared type of an expressionN2343GCC 4.3__cpp_decltype >= 200707
    decltype and call expressionsN3276GCC 4.8.1
Right angle bracketsN1757GCC 4.3
Default template arguments for function templatesDR226GCC 4.3
Solving the SFINAE problem for expressionsDR339GCC 4.4
Template aliasesN2258GCC 4.7__cpp_alias_templates >= 200704
Extern templatesN1987Yes
Null pointer constantN2431GCC 4.6
Strongly-typed enumsN2347GCC 4.4
Forward declarations for enumsN2764GCC 4.6
Generalized attributesN2761GCC 4.8__cpp_attributes >= 200809;
__has_cpp_attribute(noreturn) >= 200809;
__has_cpp_attribute(carries_dependency) == 0 (not implemented)
Generalized constant expressionsN2235GCC 4.6__cpp_constexpr >= 200704
Alignment supportN2341GCC 4.8
Delegating constructorsN1986GCC 4.7__cpp_delegating_constructors >= 200604
Inheriting constructorsN2540GCC 4.8__cpp_inheriting_constructors >= 200802
Explicit conversion operatorsN2437GCC 4.5
New character typesN2249GCC 4.4__cpp_unicode_characters >= 200704
Unicode string literalsN2442GCC 4.5__cpp_unicode_literals >= 200710
Raw string literalsN2442GCC 4.5__cpp_raw_strings >= 200710
Universal character name literalsN2170GCC 4.5
User-defined literalsN2765GCC 4.7__cpp_user_defined_literals >= 200809
Standard Layout TypesN2342GCC 4.5
Defaulted and deleted functionsN2346GCC 4.4
Extended friend declarationsN1791GCC 4.7
Extending sizeofN2253GCC 4.4
Inline namespacesN2535GCC 4.4
Unrestricted unionsN2544GCC 4.6
Local and unnamed types as template argumentsN2657GCC 4.5
Range-based forN2930GCC 4.6__cpp_range_based_for >= 200907
Explicit virtual overridesN2928 
N3206 
N3272
GCC 4.7
Minimal support for garbage collection and reachability-based leak detectionN2670No
Allowing move constructors to throw [noexcept]N3050GCC 4.6
Defining move special member functionsN3053GCC 4.6
Concurrency
Sequence pointsN2239Yes
Atomic operationsN2427GCC 4.4
Strong Compare and ExchangeN2748GCC 4.5
Bidirectional FencesN2752GCC 4.8
Memory modelN2429GCC 4.8
Data-dependency ordering: atomics and memory modelN2664GCC 4.4
(memory_order_consume)
Propagating exceptionsN2179GCC 4.4
Abandoning a process and at_quick_exitN2440GCC 4.8
Allow atomics use in signal handlersN2547Yes
Thread-local storageN2659GCC 4.8
Dynamic initialization and destruction with concurrencyN2660GCC 4.3
C99 Features in C++11
__func__ predefined identifierN2340GCC 4.3
C99 preprocessorN1653GCC 4.3
long longN1811GCC 4.3
Extended integral typesN1988Yes





C++14 지원은 아래와 버전들에서 지원되고 있습니다.



Language FeatureProposalAvailable in GCC?SD-6 Feature Test
Tweak to certain C++ contextual conversionsN33234.9
Binary literalsN34724.3 (GNU) 
4.9 (N3472)
__cpp_binary_literals >= 201304
Return type deduction for normal functionsN36384.8 (N3386) 
4.9 (N3638)
__cpp_decltype_auto >= 201304
Generalized lambda capture (init-capture)N36484.5 (partial) 
4.9 (N3648)
__cpp_init_captures >= 201304
Generic (polymorphic) lambda expressionsN36494.9__cpp_generic_lambdas >= 201304
Variable templatesN36515__cpp_variable_templates >= 201304
Relaxing requirements on constexpr functionsN36525__cpp_constexpr >= 201304
Member initializers and aggregatesN36535__cpp_aggregate_nsdmi >= 201304
Clarifying memory allocationN3664N/A
Sized deallocationN37785__cpp_sized_deallocation >= 201309
[[deprecated]] attributeN37604.9 (N3797)__has_cpp_attribute(deprecated) >= 201309
Single-quotation-mark as a digit separatorN37814.9 (N3797)__cpp_digit_separator >= 201309


반응형

STL의 map,array의 성능에 차이는 없을까?

key값이 string인 경우와 int인 경우의 차이는 얼마나 될까?

이것을 확인하기 위해서 아래와 같이 간단한 성능 테스트 프로그램을 작성해봤습니다.

 

 

stringMapTC()는 strStr 에 들어있는 string들을 key로 하여 map의 요소에 접근하는 테스트

stringUnorderedMapTC()는 strStr 에 들어있는 string들을 key로 하여 unordered_map의 요소에 접근하는 테스트

intMapTC()는 int 값을 key로 하여 map의 요소에 접근하는 테스트

intArrayTC()는 stl::array로 요소에 접근하는 테스트

cArrayTC()는 stl container가 아닌 srcStr[] 에서 직접 35번 요소에 접근하는 테스트

 
 

테스트 결과 - 10000회 수행 시간 (초)

 

함수  데이터 형식  1  2  3  4
stringMapTC()

std::map
<const std::string, int>
0.0049 0.0052 0.0054 0.0053
stringUnorderedMapTC() std::unordered_map
<const std::string, int>
0.0018 0.0019 0.0019 0.0019
 intMapTC()

std::map
<int, const std::string>
0.0006 0.0008 0.0008 0.0008
 intArrayTC()

std::array
<std::string, 100>
0.0001 0.0001 0.0001 0.0001
 cArrayTC()

char* srcStr[] 0.0001 0.0001 0.0001 0.0001
 

 

stringMapTC의 경우는 key compare를 위해 string 을 비교해야 하기에 가장 오래걸립니다.

stringUnorderedMapTC는 map에 비해 약 2.7배 정도 빠른 성능을 보입니다.

code가 길어서 그렇지 성능을 높이려면 map 쓰는 곳을 모두 unordered_map으로 변경하면 비약적인(?) 성능 향상이 이뤄지겠네요 ^^.

 

intMapTC의 경우는 key값이 int라서 string 을 key로 사용하는 것에 비해 많이 빠릅니다. 그러나 stl::array에 비해서는 느리게 결과가 나왔습니다.

당연히 intArrayTC의 경우는 당연히 map보다는 빠를 수 밖에 없습니다. 전체 서치가 아니라 array의 index (= array[index]) 를 key처럼 사용하기 때문에 key값이 당연히 정렬이 되어있어서 빠를 수 밖에 없습니다.

cArrayTC() 와 비슷한 결과가 나올 수 밖에 없습니다.

 

[source code]

#include <time.h>
#include <map>
#include <unordered_map>
#include <array>
#include <string>
using namespace std;

const char *srcStr[] =
    {
        "hello"
        "bounds",
        "contentBounds",
        "contentOpacity",
        "renderOperation",
        "opacity",
        "showState",
        "anchor",
        "anchorZ",
        "transform",
        "childrenTransform",
        "zPosition",
        "zOrderGroup",
        "clipToParent",
        "clipChildren",
        "projection",
        "surfaceOpaque",
        "name",
        "propertyPropagation",
        "implicitAnimation",
        "detach",
        "attach",
        "bounds.",
        "bounds.position",
        "bounds.size",
        "transform.",
        "transform.rotation.x",
        "transform.rotation.y",
        "transform.rotation.z",
        "transform.scale.x",
        "transform.scale.y",
        "transform.scale.z",
        "transform.translation.x",
        "transform.translation.y",
        "transform.translation.z",
        "transform.rotation.anchor.x",
        "transform.rotation.anchor.y",
        "transform.rotation.anchor.z",
        "transform.scale.anchor.x",
        "transform.scale.anchor.y",
        "transform.scale.anchor.z",
        "transform.rotation.xy",
        "transform.scale.xy",
        "transform.translation.xy",
        "transform.rotation.anchor.xy",
        "transform.scale.anchor.xy",
        "childrenTransform.",
        "childrenTransform.rotation.x",
        "childrenTransform.rotation.y",
        "childrenTransform.rotation.z",
        "childrenTransform.scale.x",
        "childrenTransform.scale.y",
        "childrenTransform.scale.z",
        "childrenTransform.translation.x",
        "childrenTransform.translation.y",
        "childrenTransform.translation.z",
        "childrenTransform.rotation.anchor.x",
        "childrenTransform.rotation.anchor.y",
        "childrenTransform.rotation.anchor.z",
        "childrenTransform.scale.anchor.x",
        "childrenTransform.scale.anchor.y",
        "childrenTransform.scale.anchor.z",
        "childrenTransform.rotation.xy",
        "childrenTransform.scale.xy",
        "childrenTransform.translation.xy",
        "childrenTransform.rotation.anchor.xy",
        "childrenTransform.scale.anchor.xy",
        "__showOpacity",
};

double stringMapTC()
{
    std::map<const std::string, int> strMap;
    int i = 0;
    for (auto str : srcStr)
    {
        strMap.insert({str, i++});
    }

    int v = 0;
    clock_t start = clock();
    for (int j = 0; j < 10000; j++)
    {
        v = strMap["childrenTransform.rotation.anchor.x"];
    }
    clock_t end = clock();
    return (double)(end - start) / CLOCKS_PER_SEC;
}


double stringUnorderedMapTC()
{
    std::unordered_map<std::string, int> strMap;
    int i = 0;
    for (auto str : srcStr)
    {
        strMap.insert({str, i++});
    }

    int v=0;
    clock_t start = clock();
    for (int j = 0; j < 10000; j++)
    {
        v= strMap["childrenTransform.rotation.anchor.x"];
    }
    clock_t end = clock();
    return (double)(end - start) / CLOCKS_PER_SEC;
}

double intMapTC()
{

    std::map<int, const std::string> strMap;
    int i = 0;
    for (auto str : srcStr)
    {
        strMap.insert({i++, str});
    }

    clock_t start = clock();
    std::string v;
    for (int j = 0; j < 10000; j++)
    {
        v= strMap[35];
    }
    clock_t end = clock();
    return (double)(end - start) / CLOCKS_PER_SEC;
}


double intArrayTC()
{

    std::array<std::string, 100> strMap;
    int i = 0;
    for (auto str : srcStr)
    {
        strMap[i++] = str;
    }

    clock_t start = clock();
    std::string v;
    for (int j = 0; j < 10000; j++)
    {
        v = strMap[35];
    }
    clock_t end = clock();

    return (double)(end - start) / CLOCKS_PER_SEC;
}

double cArrayTC()
{

    clock_t start = clock();
    std::string v;
    for (int j = 0; j < 10000; j++)
    {
        v = srcStr[35];
    }
    clock_t end = clock();

    return (double)(end - start) / CLOCKS_PER_SEC;
}

#define PRINT_TC(_FUNC)                     \
    {                                       \
        double res = _FUNC();               \
        printf("%.4f %s()\n", res, #_FUNC); \
    }
int main(void)
{

    PRINT_TC(stringMapTC);
    PRINT_TC(stringUnorderedMapTC);
    PRINT_TC(intMapTC);
    PRINT_TC(intArrayTC);
    PRINT_TC(cArrayTC);
}

 

 

테스트 결과

$ ./main
0.0054 stringMapTC()
0.0021 stringUnorderedMapTC()
0.0009 intMapTC()
0.0001 intArrayTC()
0.0001 cArrayTC()
반응형

좋은 언어와 좋은 프래임워크란 ?

언어와 framework의 발전사가 이렇다고 하고, 그러면 제목에서 적은 좋은 언어와 좋은 프래임워크란 무엇일까요?

 

가장 기본적인 기준이 되는 것이 2가지 일것 입니다.

첫번째로 프래임워크에서 제공하는 사용성과 정책이 프로그래밍 언어에서 제공하는 것과 일관되어야 합니다.

두번째는 일반적일 것 같은 동작은 그렇게 동작하도록 해야 합니다.

 

위에서 예기한 것들을 좀 살펴봅시다.

우선 첫 번째 "프래임워크와 언어의 일관성"에 대한  예를 들면, 

프로그래밍 언어에서  var A =  a; 라는 코드가 A에 a를 copy하는 것이라고 정의하고 있다면,  이 언어로 작성된 프래임워크의 MyObject obj = OldObj; 의 코드 역시 obj 에 OldObj의 내용들을 copy하는 것이어야 합니다. 그런데 만약 여기서, obj에 copy 하는 것이 아니라 OldObj의 내용을 가리키도록 동작하도록 작성되었다고 한다면,

obj의 내용을 변경했을때 왜 OldObj의 내용이 바뀌는지등에 대한 의문을 만들게 됩니다.

또는 실제 obj가 쓰일때 copy를 한다거나, obj.sync() 를 불렀을때 실제 복사가 일어난다거나 한다면, 사용자 입장에서 '=' 가 불렸을때 copy가 될 것을 기대하고 퍼포먼스를 높이기 위해 튜닝을 했는데, 실제로는 다른 timing에서 data가 copy 되기 때문에 제대로 된 튜닝을 못하게 되는 상황이 발생합니다.

이는 사용자에게  framework에서 제공하는 "=" 동작에 대해 혼란을 주는 결과가 됩니다.

이는 실수를 유발하거나 직관성을 떨어뜨리게 됩니다.

 

두번째 "일반적일것 같은 동작" 대한 예를 들어보자면,

ImageViewer class 가 있고, ImageViewer에는 Draw()라는 함수가 있습니다. 이 Draw() 라는 함수는 ImageViewer의 image를 화면에 그려주는 기능을 하는 함수입니다.

Draw()기능을 좀더 세밀하게 정의 해보자면, 

1. Draw()는 ImageViewer가 들고있는 display용 context에 image를 drawing하는 함수라고 합시다.

2. Draw()가 불렸을때 화면에 보이지는 않고 framework의 rendering 시점에 이 display context의 내용이 화면에 출력되는 방식입니다.

그런데 이 class 개발자가 Draw()가 불렸을때 image를 직접 display context에 drawing하는 것보다, rendering 시점에 display context에 drawing 하도록 하는것이 성능상 이득이라고 판단하여, Draw()함수가 나중에 drawing이 필요하다는 flag만 설정하고 나오는 것으로 정의했습니다.

Draw() 함수에 대한 정의가 좋은 방향으로 결정 된것 일까요? 옳다 그르다의 표현은 좋지 못하고, API의 직관성을 흐리는 방향으로 간것 같다는 표현이 맞죠.

 

만약 위와 같은 경우에 사용자는 ImagViewer의 Draw()호출한 다음에 Display context에서 draw된 image를 꺼내와서, 그위에 text를 더 그리려는 작업을 하려 했다면, 전혀 엉뚱한 결과를 얻게 될것입니다.

여기에서 과연 Draw()라는 함수이름에서 보여주는 직관적인 동작은 무엇인가요? 바로 drawing입니다.

즉, 만약 ImageViewer의 성능을 높이기 위해서 flag 설정을 하여 Lazy update을 구현 할 생각이었다면, 다른 이름을 사용하는게 옳습니다.

많은 방법이 있죠. requestDraw나, Invalidate(windows에서 많이 사용하는 용어죠), SetRenderingTimeDrawEnabled() 등 API이름에서 해당 목적이 명확하게 나오도록 하는 것이 더 낳았을것 입니다.

 

framework은 직관성을 유지 하면서, 일반적인으로 예상할 수 있는 동작을 기본 동작으로 하고, 다양한 옵션을 제공하는 방향으로 되어야 한다고 생각합니다.

 

다음과 같은 항목들이 대표적인 사항들일 것입니다.

- Sync call와 Async call의 구분 

- lazy update와 immediate update 

- resource 소유권에 대한 규칙 

 

이와 같은 부분들이 아마도 platform에서 일관되게 동작하도록 정의하고 정리하기 어려운 부분일 것입니다.

 

특히 Resource 라고 표현한 객체의 lifecycle 관리 즉, 객체를 생성한 주체와 삭제하는 주체에 대한 것은 아주 자주 접하는 케이스이기 때문에, 명확히 하고 일반적으로 방법(개발자들이 흔히 예상할 수 있는 )으로 제공하는 것이 맞습니다.

 

 

아주 특별하고 획기적인 기능이라 하더라도, 그게 일반적인 상식이나 생각에서 벗어난다면, 좋지 못하겠죠.

 

몇가지 예를 들어보겠습니다.

 

DDD::CreateObj()

{

   ABC* obj = new ABC;

   Dock.Set(obj);

}

 

라는 아주 간단한 code가 있다고 합시다. 이 경우 obj는 누가 관리하는 것이 맞을까요?

1. DDD class에서 해야한다.

2. Dock에서 하는 것이 맞다.

3. 가비지 컬랙터(Garbage Collector)에 맡긴다.

 

 

또 다른 예를 들어보자면, array와 list가 있다고 합시다.

C++로  SoCool이라는 프래임워크 를 개발하고 있는 탐 이라는 사람이 있다고 합시다.

탐은 Array 와 List 를 만들때, "왜 다른 언어들은 index를 0 부터 시작하지? 그래서 개수가 10개 이면 0~9까지 카운트 되게 했지? 이건 일반인들은 상상도 할 수 없는 일이야" 라고 생각했습니다. 그래서 array의 index를 0이 아닌 1부터 시작하도록 했습니다.

어떻게 생각하시나요?

 

이 생각을 바탕으로 하나씩 짚어봅시다.

 

Array의 index는 프로그래밍 세계에서는  일반적으로 0부터 시작하는 반 열린 집합 형태로 표기 됩니다.

즉 개수가 10개인 array는 0<= index<10 으로 표현하는 것이 일반적인 표현 방식이죠. 이유는 memory와 관련 있는데, array 의 변수명은 그 변수가  잡고있는 memory의 시작 위치를 표시합니다. 따라서 Array[0]의 표시는 address + 0의 위치 시작 위치로 표시되는 것이죠.

이를 실생활에서 처럼 첫번째 item이니까 Array[1] 로 표현 한다면, address + 1 -1 과 보정을 하거나 아니면, 메모리상 address +1  위치 부터 data를 사용하도록 해야 합니다. 

이 두가지 모두 Computer 구조랑 잘 맞지 않는 표현 방법이 되죠.

(생각하기 나름이긴 하지만 시스템 이나 메모리구조 등을 이해하고 있는 많은 프로그래머들의 일반적인 생각은 이렇다는 것입니다.)

 

이러한 이유에 의해서 인지는 모르지만, 결과적으로 보면, 아래와 같은 의미가 되었습니다.

개념 상 뭐 어떻게 생각하느냐에 따라 다를 수 있습니다. 하지만 수학의 집합 형태로 생각 해봅시다.

우선 수학에서 어떤 집합을 표현 할때 열린 집합, 닫힌 집합, 반 열린 집합 등의 명칭으로 분류를 하기도 합니다.

무슨 의미냐 하면, 1 부터 9까지의 숫자들의 모음(1과 9을 포함하는)을 위에서 예기한 집합으로 표현하자면 다음과 같습니다.

1. [열린집합] 0<집합<10   즉, 경계인 0을 포함하지 않고, 10을 포함하지 않는 집합.

2. [닫힌집합] 1<=집합<=9  즉, 경계인 1을 포함하고 , 9는 포함하는 집합.

3. [반 열린 집합] 1<=집합<10  즉, 경계인 1을 포함하고 , 10을 포함하지 않는 집합.

4. [반 열린 집합] 0<집합<=9   즉, 경계인 0을 포함하지 않고 , 9는 포함하는 집합.

 

Computer programming 에서는 memory addressing 방식 때문에 자연스럽게 3번 형태를 띄게 되었습니다.

Computer에서는 시작을 1부터가 아닌 0부터 시작하고 있기 때문에, 10개 라는 의미가 0~9까지를 의미하는 것이 되었기 때문이죠.

 
탐은 array에 대해서는 이해를 했고, 리스트는 고치고 싶었습니다. "그래 . array는 메모리 상에 존재하는 특정 블럭을 표현 한것이니가 그렇다 치고, 그럼 list는 논리적으로 head 와 tail을 따로 구성할 수 있고, 가변적인 데이타 구조이니까, 앞으로 우리는 list에서는 index가 1부터 시작하도록 할거야."

라고 생각하고 list의 index를 1부터 시작하는 것으로 제공하기로 하였습니다.

 

만약 list 의 index를 1부터 시작하겠다고 하는 것은, "2번 닫힌 집합으로 표현 해라." 라는 의미가 되는 것입니다. 즉, 10개가 있다는 의미가 1~10까지 닫힌 집합으로 표현해야 한다가 되는것이고,  code로는   1<= index <=10 이라는 의미가 되는 것이죠.

array에서는 0<=index<10 이고, list에서는 1<=index<=10 이라고 표현 하면, 결국 data의 집합을 표현 하는 자료 구조인데 한 언어나 프래임워크 내에서 서로 다른 규격을 제시 하는 것이 됩니다. 

 

이런 비슷한 기능을 제공하는 class들이 각각 다른 기준의 동작을 유도하는 것은, 어플리케이션 개발에 수많은 혼선을 줄 가능성이 있습니다.

단순히 list와 array의 차이가 아니라, 어떤 API들도 직관적으로 접근 할 수가 없고, 숨은 의도들을 파악해야 하는 상황이 발생하죠. 

위의 경우, 어플리케이션 개발자는  "아 array는 memory 블럭을 잡는 것이니까 index는 0 부터 사용해야 하고, list는 동적이기 때문에 메모리 블럭과 관련이 없어 그러니까 프로그래머가 아닌 일반적인 사람 입장에서 생각해서  index가  1부터 인거야, 이건 꼭 외워야 해. 나중에 index array와 list간의 index변환도 고려 해야 하니까. 이런게 또 뭐가 있을까? Stack ? Stack은 어떻게 동작하지?" 라는 생각을 하게 할겁니다.

 

 

전반적인 S/W 도메인 별로 보면 여러 주제들 예를 들면 Synchronous와 Asynchronous, mutable, thread, lock, ipc, data binding, runtime, reflection 등등, 이러한 요소들을 프레임워크와 언어에 대해서 일관성, 과 일반적이고 상식적인 기본 동작과 컨셉을 가져가야 할 것인지를 잘 정리하고 제공되어야 좋은 플랫폼 또는 프래임워크 라고 할 수 있을 것입니다.

 

이런 이유에서 규모가 큰 S/W 회사들은 , 프래임워크 구축하려 할때, 기존의 언어로 새로운 패러다임을 반영하기 힘들거나 , 프래임워크에서 제공하려는 기능이 기존의 언어로 표현이 힘들 경우, 새로운 언어들을 만들기도 하는 것입니다. (C#, Java가 대표적이랄까요?)

 

 

'개발 Note > UI Framework 개발하기' 카테고리의 다른 글

Core Image Concepts  (0) 2011.09.20
stdafx.h 를 없애보자!  (0) 2011.08.18
CoreAnimation in iOS  (0) 2011.07.13
key - value 관리  (0) 2011.06.08
[애자일] 릴리즈 계획 과정에서 가장 중요한 것들  (0) 2010.10.29
반응형

 

항목 11 :

 

우리가 class를 설계할때, 의도되지 않은 동작을 막기 위해 클라이언트에서 호출 할 수 없도록 막을 필요가 있습니다.

하지만, 특수 멤버 함수들인 C++이 필요에 따라 자동으로 작성된 멤버 함수들에서 이런 제한이 쉽지 않습니다.

특히 , 복사생성자, 대입 연산자등 몇몇에 대해서 private으로 정의하는 경우들이 있습니다.

 

class A{

public:

   int get() const;

   int set(int d);

private:

   A(const A& rhs); // unused ( or not defined)

   A& operator =(const A&); // unused (or not defined)

};

 

이에 관한 언급을 한 것이 11 항목입니다.

 

 

C++11에서는 이를 위한 더 나은 방법을 제공하는데요. 바로 delete 키워드입니다.

public:

  A(const A& rhs) = delete;

  A& operator =(const A* rhs) = delete;

 

이런 형식입니다. 앞으로 이런 형식을 삭제된 함수라고 표현 하겠습니다.

 

뭐가 더 나아졌지? 라는 의문을 가질 것입니다.

 

첫번째는 A(const A&rhs)를 사용 못하게 하기 위해서 선언했다는 표현을 주석으로 할 필요가 없어졌다는 것입니다.

만약, 주석이 없다면 오해의 소지도 약간 있죠.. 

 

두번째는 흥미로운 내용인데, 삭제된 함수는 private이 아니라 public으로 선언하는 것이 관례입니다.

이유는 , 클라이언트 코드가 멤버함수를 사용할때 먼저 접근성을 봅니다. 그리고 나서 삭제 여부를 확인합니다.

따라서 만약 삭제된 함수가 private이었다면, 먼저 private함수를 사용했다는 에러를 보이게 됩니다.

 

삭제된 함수는 접근 권한이 중요한 것이 아니라 의도적으로 삭제한 것이 더 중요한데도 말이죠.

그래서, 오류의 원인이 더 명확하게 밝혀지도록 public으로 선언하는 것입니다.

 

 

 

삭제된 함수의 두 번째 장점은, 어떤 함수에도 적용할 수 있습니다. 

private으로 제한 하는 방법은 class의 멤버 함수에만 사용할 수 있습니다.

 

예를 들어,

bool isLucky(int num); 라는 함수가 있다고 하면,

 

if( isLucky('a'))...

if( isLucky(true)) ...

if( isLucky(3.5)) ...

 

"의도된 코드인가" 라는 질문에는 '아니요' 가 정답이죠. 그러나 'a' 나 true 나 3.5나 모두 빌드되고 실행도 됩니다.

 

이를 엄격히 제한하고자 한다면,

bool isLucky(char) = delete;

bool isLucky(bool) = delete;

bool isLucky(double) = delete;  // double 과 float 을 배제

 

이렇게 되면, 'a' true 3.5f 모두 오류가 발생합니다.

 

 

삭제된 함수의 세 번째 장점은 

클래스 안의 함수 템플릿의 일부 인스턴스화를 방지하려는 목적으로 private을 이용하는 것은 불가능합니다.

아래 코드를 살펴보면 이해가 쉽습니다.

class Widget{

public:

 ...

  template<typaname T> 

  void processPointer(T* ptr)

   {...}

private:

   template<>

   void processPointer<void>(void*); // 오류가 발생함.

};

이 코드가 불가능한 이유는 템플릿 특수화는 반드시 클래스 범위가 아니라 이름공간(namespace) 범위에서 작성해야 한다는 것입니다.

따라서 다음과 같이 삭제된 함수를 사용해야 합니다.

 

class Widget{

public:

 ...

  template<typaname T> 

  void processPointer(T* ptr)

   {...}

};

 

template<>

void Widget::processPointer<void>(void*) = delete;

 

 

 

 

자신이 작성했던 코드를 delete로 바꾸고 컴파일 해봅시다.!!! ㅎ

 

 

[참조] effective modern c++ :항목 11

+ Recent posts