[Clean Code] 클린 코드 법칙

개발자 누구라면 깔끔한 코드를 원할 것이다. 나는 평소에 리팩토링, 클린 코드등에 괜히 관심히 많았다. (그렇다고 내 코드가 깨끗하다고는 못하겠다.) 처음으로 HOWTO 같은 종류가 아닌 개발 서적을 처음으로 산 책이 로버트 마틴의 ‘클린 코드’이다. 몇주 전 사내에 로버트 아저씨(실재로 백발의 할아버지이다.)가 같은 주제로 자신이 만든 동영상 시리즈 링크가 돌길래 하루에 한개씩 1.5배 속도로 시청하고 있다. 책에 나온 이야기를 재미있게 설명하고 있어서 귀에 속속 들어왔다. 한번 보고 스쳐 지나간다면 또 까먹을지 모른다는 두려움으로 노트에 핵심 포인트만 작성하기 시작했고, 노트도 나중되서 없어지만 안되겠다는 생각에 블로그에 정리를 한번 해보려고 한다. 이 글을 읽고 클린 코드에 관심이 생긴다면 책도 한번 사보길 권한다. 팀 단위로 일하는 소프트웨어 엔진이어라면 꼭 권하고 싶다. 링크

네이밍 (Naming)

  • 좋은 고드란? 사람들이 예상한 대로 작동하는 코드이다.
  • 좋은 네이밍은 타인과 소통할 수 있는 기본적이고 가장 중요한 도구이다.
    • 네이밍에서 의도가 나타나야 한다.
    • 해결하고자 하는 문제가 묘사되어야 한다.
    • 잘못된 정보는 절대 넣지 마라.
    • 클래스명, 변수명은 명사를 사용하여 작명하라.
    • 함수명은 동사로 시작해야 한다.
    • enum은 형용사로 시작한다.
    • 발음이 가능한 단어를 사용하자.
    • 변수의 타입을 나타내는 Prefix은 이제 그만 사용하자. 발달한 IDE가 해결해준다.
  • 이름이 사용되는 범위에 맞게 작명해야한다.
    • 변수는 범위가 광범위 할 수록 의도와 정확한 정보로 비교적 길게 작명하여 어디에서든지 이해가기 쉽게 만드는 것이 좋다.
    • 변수의 범위가 작을수록 간단하고 짧게 만드는 것이 가독성을 높이는 것에 좋다.
    • 클래스와 함수는 변수와 반대 되는 법칙을 따른다. 사용되어지는 범위가 넓을 수록 이름을 짧게 짓고, 범위가 좁을 수록 길게 지어서 정확히 무슨 일을 하는 묘사하자.

함수 (Function)

  • 함수의 크기가 작으면 작을 수록 좋다. 얼마나? (4줄~6줄)
  • 작명을 잘해야 한다.
  • 한가지 일만을 하자. 한가지 일만 하는지 알기 위해서 코드를 추출 (extract)이 안될 때 까지 추출한다.
  • 작은 크기의 함수들이 많아지면 함수 호출 오버해드나 가독성이 떨어진다고 생각한다면 그것은 오해이다.
    • 작은 크기의 좋은 작명이 된 함수가 많다는 것은 복잡한 길에 가고자 하는 길을 안내해줄 표시판이 많은 것 처럼 좋은 일이다.
    • 함수 호출 오버해드 (function call overhead)가 걱정되는가? 현대시대의 개발장비 성능은 옛 장비와 다르게 빨라졌기 때문에 나노 초도 걸리지 않으며, 여러 사람과 함께 용이 작업에 있어서 높은 가독성이 가져다 주는 혜택이 더 크게 보여진다.
  • 큰 함수의 구현을 클래스로 추출하여 크기를 줄여보자. 호출하는 곳에서는 새 클래스의 invoke()를 호출하고 중복 코드를 하나로 묶고, 더 이상 줄일 수 없을 때 까지 줄여 작은 단위의 함수로 구현을 분배하자.

함수 구조 (Function Structure)

  • 함수의 인자(Argument)의 갯수는 적을 수록 좋다. 1~2개가 적당하다. 3개 이상이 되면 오프젝트로 묶어서 전달하자.
  • output 인자는 절대 사용하지 말자. 전달된 인수의 필드나 프로퍼티를 변경하여 함수 밖에서의 사용하지 말자.
  • 함수 인자로 Boolean 타입의 인자는 사용하지 말자. Boolean 타입의 인자를 사용한다는 것은 함수 내에서 2가지 이상을 하겠다는 것을 공식적으로 선언한 것이기 때문이다. 함수는 한가지 일만 하는 것을 원칙으로 하자.
  • Nullable 인자는 지향하자. 물론 Open Source과 같이 불특정 인원이 어떤 것을 전달할지 모를 때면 사용하여 방어적 코드를 짜야겠지만, 팀내에서는 합의하에 절Nullable 인자를 사용하지 않고 공격적인 코딩 스타일을 고수하자.
  • Step Down 법칙: Public 변수나 메소드를 위에 넣고, private 메서드를 아래에 넣는 코드 컨밴션은 유행이 한참 지난 스타일이다. 잡지나 신문을 보면 제목이 나오고 자세한 내용은 그 후에 따라 나온다. 이와 같이 하면, 비록 Public 메서드들이 한눈에 안들어 올 것이다. 하지만 코드의 가독성을 위해서 Step Down 법칙을 추천한다.

Step Down Rule

 

  • Switch-case 문: 사용을 지향한다. Switch 문을 사용하게 되면 코드가 의존도가 높아진다. 대신하여 Polymorphism 방식을 사용하자.

No Switch statement

  • Command & Query: 함수의 특성을 광범위적으로 보면 크게 두가지 종류로 구분하여 사용하는 것을 추천한다.
    • Command : 반환 값은 없어야 하며 어떤 행동, 혹은 명령을 실행하는 함수라고 할 수 있다. 예를 들어 authenticator.login()라는 함수는 로그인을 하는 행동을 하는 함수이다. 꽤 자주 많은 곳에서 login과 같은 메서드에 User 오브젝트를 반환하는 경우를 볼 수 있다. 명령 성질의 함수에 반환을 하게 되면 Query 종류의 함수도 아니고 Command 종류의 함수도 아닌 두 가지 일을 하는 함수가 되어 버린다. 물론 Nil을 반환하여 로그인 실패를 체크하려는 의도도 있을지 모른다. 하지만 이런 박쥐 같은 함수는 타 개발자에게 혼란을 가중시킨다.
    • Query: 값을 반환하는 함수를 말한다.
  • Null를 반환하지 말자. 만약 Null이 될 것 같으면 Exception을 던지자.
  • try문은 함수의 가장 위에 사용하자. 여기에 언급되는 함수 구조의 룰은 전부 함수가 한가지 일만을 명확하게 하고 짧은 함수들을 전재를 한다.

 

형식 (Form)

  • 모든 파일의 형식은 일관성이 중요하다. (인던테이션, 줄 바꿈, 주석 등)
  • 주석: 오래된 레가시 코드에는 업데이트를 하지 않은 주석이 많다. 주석은 Public API 문서에서는 불특정 다수에게 유용함을 주지만 코드 자체가 주석을 대신해야 좋은 코드이다.
  • 파일 크기는 최대한 작을 수록 좋다. 500 줄 이상이 되지 않게 조심하자.
  • 적절한 코드 가로 길이는 화면에 보이는 곳 까지이다. 줄 바꿈 없이 한 눈에 코드가 읽혀지는 것이 좋다.
  • 실제 구현에서 직접적으로 구현체 클래스 (concrete class)를 호출하기 보다는 추상 클래스를 호출함으로써 확장성 확보하자.

TDD (Test Driven Development)

  • 개발자는 현존하는 코드에 손을 대길 꺼려 한다. 그 이유는 잘 돌아가던 것이 깨질까 봐 그렇다. 하지만 코드가 깨지는 지 안깨 지는 보장 받을 수 있으면, 지저분한 코드를 더 깔끔한 코드로 바꾸려고 노력할 가능성이 높다. 그래서 테스트가 필요하다.
  • 그런데 왜 TDD인가? 이름에서 느낄 수 있는 것 처럼 Test code의 중요성은 아무리 강조해도 부족하다. 중요한 것을 먼저 짜는 것이 좋은 습관이다. Production code를 먼저 짜게 되면 Test case를 소흘하게 여길 것이다. 뿐만 아니라 좋은 설계를 갖게 될 것이다. 좋은 설계는 유연하고, 유지보수 가능해야하며, 확장 가능해야 한다. 그러기 위해서 코드가 깨지는 지 안깨지는 확신을 해야한다.
  • TDD의 세가지 법칙
    • 실패한 Test case를 패스하기 위해 만든 것 외에는 절대 Production code를 짜서는 안된다.
    • 실패할 만큼만 Test case를 짠다.
    • 실패한 Test case가 패스 할 만큼만 Production 코드를 짜라
  • 순서 (Red -> Green -> Refactor)
    • Red: 실패할 만큼만 Test case를 짠다.
    • Green: 실패한 Test case가 패스 할 만큼만 Production 코드를 짜라.
    • Refactor: Test case를 포함해서 코드를 정리하라.

설계 (Architecture)

  • 소프트웨어 개발에 있어 훌륭한 설계는 최대한 개발환경에 대한 결정을 안 할수 있는 설계이다. 개발을 시작하기 전에 우리는 Use case 보다 사용할 Tool과 Framework에 얽매이는 경우가 많다. 또한 이렇게 결정된 사항에 맞추어 설계가 진행되는 경우가 대부분이다. 하지만 이렇게 되면 각 tool이나 framework에 의존도가 높아져 유연한 설계를 할 수 없게 만든다.
  • 좋은 설계자란 tool과 framework와 같은 개발 환경에 대한 결정 사항들을 최대한 유연하게 하고, 미루고 미룰 수 있는 자이다. 예를 들어 데이터 저장을 어떤 방식으로 할지 결정을 나중에 해도 될 만큼 유연한 설계를 짜는 사람이 진정 좋은 설계자라고 할 수 있다. Sql를 사용할지 file system을 사용할지 웹 API를 사용할 지 등을 설계 초입에 안하고 설계할 수 있어야 한다.
  • 개발 환경 보단 Use case에 더 집중하도록 하자.
  • UI 작업을 Use case의 플러그인 정도로 생각을 하고 설계를 하자. 보통 UI 작업은 꽤 비싼 작업이다. UX/UI design/UI dev등 상당히 많은 노력과 시간이 필요한 부분이다. 하지만 Use case 입장에서 나중에 UI이가 Web page에서 Command line으로 바뀌거나 stand alone 어플리케이션으로 바뀐다 해도 큰 지장 없는 설계, 즉 UI 레이어를 Use case의 플로그인 정도로 생각하고 설계를 해야한다.
  • Use case 란?
    • 사용자와 시스템이 특정 목적을 달성하기 위한 설명서 이상, 이하도 아니다.
    • 유스케이스 주도적 개발 (Use case driven development)은 보다 더 나은 설계를 줄 것이다.
    • Use case와 전달 방식 (delivery mechanism)와 분리되어야 한다.

[++, --] 소소한 프로그래밍 이야기 – 1

프로그래밍을 하면서 정말 기본적인 개념인데 가끔 햇갈리는 것들이 있을 것이다. 크게 어려운 개념도 아닌데 원낙 가끔 사용하다 보면 생기는 현상인 것을 때로는 머리 나쁜 자신을 탓할 때가 있다. ^^

이 글은 다름이 아닌 ‘증강 연산자와 감소 연산자 (Increment and Decrement Operators)’에 대해서 간단한 노트이다. 보통 연산자 ‘++’와 ‘–’를 가장 많이 사용하는 경우는 아마도 for 문이 아닐까 싶다. 항상 별 큰 생각 없이 ‘i++’를 찍어왔었던 내가 문득 학부때 배운 기억이 나는데 prefix으로 붙이는 것과 postfix로 붙이는 것과 무슨 차이가 있는지 생각이 가물가물해서 찾아보았다.

i++i = i + 1 혹은 i += 1와 동일하게 i의 값을 1씩 올려준다.  i의 값만 하나씩 증강 시키거나 감소 시기키 위해 ‘–’를 사용할 때는 피연산자 앞에다가 붙이든, 뒤에다가 붙이든 상관이 없다. 하지만! 이 연산자는 값을 return 해주기 때문에 다른 변수에 할당하게 될 때는 이야기가 달라진다.

  • 만약 연산자를 변수 앞에다가 붙이면, 변수에 대입해주기 전에 값이 올라 가므로 기존 값에서 1이 더해진 값이 대입된다.
  • 하지만 만약 연산자를 변수 뒤에다 붙이면 변수에 값이 올라가기 전 먼저 대입이 이루워지므로 기존의 값이 할당이 된다.

코드를 살펴 보자.

Screen Shot 2015-04-21 at 5.38.57 PM

 

(귀찮아서 스크린 캡처를 했으니 아마 복사는 안될 것이다. 물론 간단한 코드를 복사할 사람은 없을 것을 예상 되지만.)

위 예제와 같이 prefix으로 연산자를 사용 하는 것과 postfix로 연산자를 사용하는 것과 다른 결과가 나오게 된다. 뭐 나만 기억을 못하는 정말 작고 사소한 것일지 모르지만 동감하는 분들이 분명 어딘가 있을 것으로 기대한다.

[C 언어] 포인터 기본 개념

iOS 개발자들은 여러가지 언어를 사용하여 개발을 할 수 있다. 주류는 C 언어 개열의 Objective-C일 것이며, 새로나온 Swift를 사용해서 개발을 참여 할 것이다. 그런데 학부때 배운 C 언어의 가장 헷갈리는 개념을 뽑으라고 한다면 ‘포인터’일 것인데, 알고리즘 책을 들고 공부하다 보면 대부분의 예제가 C 코드로 되어 있어 한번 더 remind할 겸해서 리서치 해본 노트를 올려본다.

pointer-to-pointer

 

 

Definition

  1. Pointer 변수: 값이 저장되어 있는 변수의 주소를 담고 있는 변수.
  2. Dereferencing a Pointer: 가리켜고 있는 주소의 해당하는 실제 값을 뜻함.
  3. * : 해당 주소에 있는 값 연산자 (Value at address operation)
  4. & : 주소 연산자 (Address of operator)
  5. -> : 구조체 값의 데이터 접근하기

When to use?

  1. * : 포인터 변수를 선언 할 때 / Dereferencing 할 때 사용됨.
  2. & : 변수의 저장 주소를 참조 할 때 사용됨.
  3. -> : (예. ptr -> name(*ptr).name 과 동일함)

이렇게 생각 해보자.

포인터 변수 == 편지 봉투

& 포인터 변수 == 봉투에 적힌 주소

*포인터 변수 == 주소가 가리키는 실제 건물

마치며…

블로그 검색하다가 찾은 내용을 간략하게 노트에 적은 것을 잊어버리지 않기 위해서 정리해보았다. 더 자세한 내용을 코드와 함께 보기 원한다면 아래 링크를 참조하자.

http://denniskubes.com/2012/08/16/the-5-minute-guide-to-c-pointers/

[펌글] 3D 기본 수학

해당 포스트는 iOS의 Core Animation을 공부하다가 본 좋은 블로그라 생각하여서, 링크를 공유해본다.

Basic 3D Math: Matrices by Egon Rath’s Notes

Basic 3D Math: Matrices

Matrices are rectangular mathematical objects which have a number of rows and columns – think of it as a two-dimensional array. Take a look at the following:

A = delim{[}{matrix{3}{4}{1 2 3 4 5 6 7 8 9 10 11 12}}{]}

Above is a 3×4 Matrix (because it has 3 rows and 4 columns) – speak: 3 by 4 Matrix. Each element of the Matrix can be indexed by using the following notation:

A_ij where i is the row and j the column: A_32 = 10 because the element at the 3rd rows and 2nd column has the value 10.

Matrices are used in CG to represent a various number of different things like transformations and orientations.

Part 1: Multiplying Matrices (Matrix Product)

Matrix multiplication is not commutative, which means that the order of operation is relevant (as opposed to the multiplication of real numbers). In order to be able to multiply two matrices they must satisfy the rule that column of the first must match the rows of the second. Take a look at the following graphic which works as a simple reminder for the rules of matrix multiplication:

But what’s the purpose of multiplying matrices? In 3D Programming you do Transforming a vertex with such a operation. Stop – how can i multiply a vector (which stores a vertex position) with a matrix? Vectors can be thought as Vectors with 1 Row and 4 Columns – and because multiplying a 1×4 Matrix with a 4×4 Matrix is a valid operation this works.

In the first step, lets examine how to actually do the multiplication – formally this looks like:

(AB)_ij = sum{k=1}{p}{A_ik B_kj}

i = row index
j = column index
p = number of columns of the first matrix (or number of rows of the second one)

Because a example often says more than thousand words, take a look at the following:

We have two matrices: A = delim{[}{matrix{2}{3}{1 2 3 4 5 6}}{]} and B = delim{[}{matrix{3}{2}{10 11 12 13 14 15}}{]}. Multiplication of those two is possible because the number of columns of A matches the number of rows of B – the result is a 2×2 Matrix.

Let’s perform the Calculation step by step.

Step 1: Write down the calculation of every index for the resulting matrix

C_{i=1,j=1}=1*10 + 2*12 + 3*14 C_{i=1,j=2}=1*11 + 2*13 + 3*15
C_{i=2,j=1}=4*10 + 5*12 + 6*14 C_{i=2,j=2}=4*11 + 5*13 + 6*15

Step 2: Do the calculations

10 + 24 + 42 11 + 26 + 45
40 + 60 + 84 44 + 65 + 90

results in:

C = delim{[}{matrix{2}{2}{76 82 184 199}}{]}

Part 2: Creating Matrices for Transformations

As mentioned above at the beginning of this document, matrices can be used to transform vectors. Its obvious that you need corresponding matrices which represent the transformation, so they are presented below – please note that they are for OpenGL only (The “why” is discussed at the end)

Identity Matrix:

I = delim{[}{matrix{4}{4}{1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1}}{]}

The Identity matrix can be seen as the “reset” state matrix. If you multiply a vector with the Identity matrix you get the original vector. You initialise new matrices to the identity.

Translation Matrix:

T = delim{[}{matrix{4}{4}{1 0 0 X 0 1 0 Y 0 0 1 Z 0 0 0 1}}{]}

X, Y and Z represent the amount you want to translate the vector on the axis.

Scaling Matrix:

S = delim{[}{matrix{4}{4}{X 0 0 0 0 Y 0 0 0 0 Z 0 0 0 0 1}}{]}

X,Y and Z represent the amount of scaling on the corresponding axis.

Rotation Matrix:

There are four rotation matrices – one about each Axis (X,Y and Z) and one for rotating about an arbitrary axe. alpha is the roation in radians.

Rot_X = delim{[}{matrix{4}{4}{1 0 0 0 0 {cos(alpha)} {-sin(alpha)} 0 0 {sin(alpha)} {cos(alpha)} 0 0 0 0 1}}{]}  Rot_Y = delim{[}{matrix{4}{4}{{cos(alpha)} 0 {sin(alpha)} 0 0 1 0 0 {-sin(alpha)} 0 {cos(alpha)} 0 0 0 0 1}}{]}  Rot_Z = delim{[}{matrix{4}{4}{{cos(alpha)} {-sin(alpha)} 0 0 {sin(alpha)} {cos(alpha)} 0 0 0 0 1 0 0 0 0 1}}{]}

The matrix used to rotate about an arbitrary axis is a little bit more complicated.

Assumptations:

c = cos(alpha) s = sin(alpha) t = 1-cos(alpha)

Then the matrix looks like:

Rot = delim{[}{matrix{4}{4}{{tX^2+c} {tXY + sZ} {tXZ - sY} 0 {txY - sZ} {tY^2+c} {tYZ + sX} 0 {tXY + sY} {tYZ - sX} {tZ^2+c} 0 0 0 0 1}}{]}

The Vector (x,y,z) which represents the rotation axis must be normalized

Most of the time you don’t need to create those matrices by ourself because either the math library you are using provides them or you write your own.

Part 3: Order of operation and combining transformations

The order of multiplying multiple transformation matrices is cruical. In OpenGL you get the final transformation by reading your statement from left to right. Example:

vec{U} = R * T * vec{V}

R is a rotation, T a translation matrix. The Vector V is first Translated and then rotated. Take a look at the pictures below to see the difference visually:

In this Picture, the vertices of the Object are first multiplied by a rotation matrix (about Z) – which rotates the local object coordinates. After that a translation matrix (move along X)  is applied, so the object moves along the rotated X axis. The order of the multiplications are:

vec{U} = M_{trans} * M_{rotation} * vec{V}

As mentioned before, we read from right to left (Take Vector V, then Rotate, then Translate)

This time we first multiply with a translation matrix (translate along X) and then apply a rotation matrix:

vec{U} = M_{rotation} * M_{translation} * vec{V}

Which means: Take Vector V, then translate, then rotate.

Please note that the order only applies to OpenGL. In DirectX it’s from left to right – also the matrices are a little bit different in how they look like.

Part 4: Going ahead

Most OpenGL based 3D Libraries and Toolkits provide easy ways of creating the matrices mentioned above (i REALLY like Richard Wright’s Math3D Library which he uses in his Book OpenGL Superbible).

If you want to dig deeper into the mathematics behind 3D Graphics, i highly recommend you the following two books:

[Facebook-Tweaks] 간단하게 살펴보기.

Tweaks Framework by FB

이틀 전 (May.24.2014) 페이스북에서 iOS 프래임워크 하나를 Github에 올리면서 공개를 했다. 해당 프래임워크의 주 기능은 간단하다. 완성된 output의 사소한 속성들을 변경하고 싶을 때 개발자의 손에 걸치지 않고 Runtime으로 수정 가능한 기능을 제공해 준다는 것이다. (아마 무슨 뜻인지 이해가 가질 않을 것으로 생각된다.)

 

“Why do I need it?”

예를 들어 개발자가 애니메이션의 Duration을 정해서 컴파일을 할 것이다. 그런데 모션 그래픽 디자이너라든지 기획자가 보기에 너무 길다던가 맘에 안들 수 있다. 그런데 일일이 개발자 옆에 앉아서 테스트 해보거나 혹은 Bug Tracking System 같은 경로를 통해서 이와 같은 다양한 주문을 시도할 것이다. 하지만 이런 과정은 프로젝트 전체를 보았을 때 상당히 값이 비싼 비용이다. 개발자와 디자이너와 신경전을 한 두번 해본 개발자라면 이 프래임워크의 큰 가치를 깨달을 것이다.

 

“What is ‘Tweaks’?”

Tweaks는 이런 문제점을 해결해주는 좋은 대안이 될 수 있다. 프래임워크를 사용하여 디자이너 혹은 기획자가 직접 UI의 속성을 바꿔가면서 테스트해볼 수 있는 대안이 생겼기 때문이다.

from github

위 gif 이미지를 잠시 보자. ‘Tweaks’라는 UILabel 객체가 화면에 있다. 그런데 어떤 이유에서든지 디자이너가 색상이 맘에 들지 않아서 이를 변경하고자 한다. 일반적으로 디자이너는 개발자에게 이메일을 보내거나 가끔은 자리에 찾아와 색상 변경을 요구하며 이것 저것을 테스트 해보길 요구할 것이다. 이럴 때에 개발자에게 있어서는 얼마나 방해가 되는 일인지 모르며 이런 작은 방해들이 점점 모여서 프로젝트의 비용을 점점 비싸게 만드는 것이다. 그런데 (개발하기 나름이겠지만… ) 본 프래임워크를 적용해서 폰을 흔들면 UI 속성을 바꿀수 있는 TableView가 나온다. 그럼 해당 UI의 속성을 바꿈으로 개발자의 손을 빌리지 않고 이것 저것 tweaking을 할 수 있는 길이 생긴 것이다.

 

“How to use?”

github 페이지에 설치 방법 부터 사용 방법이 잘 나와 있다. 가장 간단히 설치할 수 있는 방법은 CocoaPod를 사용하는 것이다. 소스코드의 순서를  간단하게 보면 다음과 같을 것이다.

  1. 프래임워크 Import 함.
  2. FBTweakViewController를 화면에 뿌릴수 있는 장치를 만듬.
  3. UI 객체 인스턴스의 속성에 바인딩 혹은, ‘FBTweaksValue’를 통해  설정 값 할당 함.

 

프래임워크 Import 하기

  1. #import <FBTweak/FBTweak.h> //FBTweak 기본 헤더파일
  2. #import <FBTweak/FBTweakShakeWindow.h> //폰을 흔들어 FBTweaksViewController를 열고 싶을 때 사용하기
  3. #import <FBTweak/FBTweakInline.h> //FBTweakInline 객체 사용할 때 필요
  4. #import <FBTweak/FBTweakViewController.h> //FBTweakViewController를 presentViewController:animated:completion:을 통해 열때 필요

 

FBTweakViewController를 화면에 뿌릴 장치

변경 가능한 UI 속성을 제어할 UITableView를 화면에 나타내주기 위해서 크게 두 가지 방법이 있을 것이다. 첫 번째는 폰을 흔들어서 나타나게 하는 방법과 임시의 버튼을 만들어서 presentViewController:animated:completion: 메서드를 사용하여 FBTweakViewController 객체를 화면서 나타나게 하는 방법이다. 둘 중에 편한 방법으로 사용하면 될 것이라고 생각 되어진다.

 

UI 속성 바인딩 혹은 설정 값을 Tweaks 함수를 통해 할당

이제 자신이 디자이너들이나 타인들에게 Runtime 때에 변경 가능한 UI 속성을 주고자 하는 코드에 FBTweakValue 함수를 통해서 값을 할당 하든지, FBTweakBind 함수를 통해서 값을 바인딩하면 된다.

  1. //#. Binding 예
  2. UILabel *_label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, _window.bounds.size.width, _window.bounds.size.height * 0.75)];
  3. _label.textAlignment = NSTextAlignmentCenter;
  4. _label.numberOfLines = 0;
  5. _label.userInteractionEnabled = YES;
  6. _label.backgroundColor = [UIColor clearColor];
  7. _label.textColor = [UIColor blackColor];
  8.  
  9. //1-a
  10. _label.font = [UIFont systemFontOfSize:FBTweakValue(@"Content", @"Text", @"Size", 60.0)];
  11.  
  12. //1-b. UILabel 객체의 텍스트 속성을 동적인 값으로 바인딩
  13. FBTweakBind(_label, text, @"Content", @"Text", @"String", @"Tweaks");
  14.  
  15. //1-c. UILabel 객체의 알파 속성을 동적인 값으로 바인딩
  16. FBTweakBind(_label, alpha, @"Content", @"Text", @"Alpha", 0.5, 0.0, 1.0);

‘FBTweakBind’ 함수 사용법은 다음과 같다.

  1. FBTweakBind(object_, property_, category_, collection_, name_, …)

  • object: UI 오브젝트 인스턴스
  • property: 객체 속성명
  • category: TableView에 나올 TableViewCell 명
  • collection: grouped tableView에 표시 될 그룹 명
  • name: 해상 TableViewCell에 표시 될 title 명
  • …: 기본 설정 값

‘FBTweakValue’ 함수 사용법은 다음과 같다

  1. FBTweakValue(category_, collection_, name_, …)

  • category: TableView에 나올 TableViewCell 명
  • collection: grouped tableView에 표시 될 그룹 명
  • name: 해상 TableViewCell에 표시 될 title 명
  • …: 기본 설정 값

그리고 나서 뒤에 오는 값들은 기본 설정 값이다. 이 기본 설정에 따라 TableViewCell에 나타날 설정 가능하도록 해주는 UI가 결정이 된다. 1-b에는 NSString인 ‘Tweaks’로 설정되어 있고, 1-c에서는 세개의 값이 있다. 첫 번째 값인 0.5는 디폴트 값이며, 두번째는 설정 가능한 가장 낮은 값, 세번째 값은 설정 가능한 가장 큰 값이다. 이렇게 설정을 하면 UIStepper를 통해 설정이 가능하게 해준다. 만약에 이 값에 YES와 같은 Bool 값이 들어오면 Toggle 가능한 UISwitch가 들어 올 것이다.

Where to go next?

github에 올라온 소스를 자신의 컴퓨터에 클론하여 예제 앱을 사용해 보면 자신의 프로젝트에 어떻게 사용할지 쉽게 알게 될 것이다. 위에 설명한 것들은 정말 기본적이고 쉬운 것들이고, 더 advance한 사용은 github에 나와있는 설명과 stackoverflow를 통해 알아보기 바란다. 혹자도 기존 프로젝트에 적용해보고 추가할 내용이 생기면 추후에 본 블로그를 더 업데이트 하겠다.

개발자을 위한 iOS7 디자인 Tips

Design?

개발자는 개발만 한다?! 비쥬얼 베이직의 아버지 ‘앨랜 쿠퍼‘가 ‘정신병원에서 뛰쳐나온 디자인‘이라는 책에서 주장했던 내용이다.

하지만 iOS 개발자라면 크게 인정하지 못할 이야기일지도 모른다. 많은 개발자가 cool한 애플의 UI/UX에 매료되어서 개발을 시작한 사람들이 많을 것이기 때문이다. 하지만 나는 전적으로 그의 주장에 공감하는 편이었다. 하지만 요즘 드는 생각은 개발자도 기본적인 디자인 요소에 대해서 알아야한다는 것이 내 생각이다. 아는 것과 모르는 것은 분명 고민을 한 결과물과 고민 없이 만든 결과물과 나오는 효과나 반응이 분명 큰 차이가 있다고 생각하기 때문이다.

다음 가이드는 내가 즐겨찾는 블로그에서 본 내용을 정리해 보았다. 조금이나마 도움이 되길 바란다.

출처 Ray Wenderlich

기본에 집중하라

  • Contrast(대조/대비)

    • 하이라이트: 화면에서 중요한 부분은 강조되어야 한다.
    • Eye candy
    • 상태: 각각의 UI가 터치 가능한지 알려줘야 한다.
    • 가독성: 글씨가 잘보이는 확인하라.

 

 

Screen Shot 2014-03-21 at 12.16.43 PM

Screen Shot 2014-03-21 at 12.16.55 PM

  • Repetition(반복)

Screen Shot 2014-03-21 at 12.19.54 PM Screen Shot 2014-03-21 at 12.20.04 PM

  • Alignment(정렬)

alignment

  • Proximity(근접)

Screen Shot 2014-03-21 at 12.24.16 PM

Screen Shot 2014-03-21 at 12.24.28 PM

  • Typography(글꼴)

    • 최대 3가지 다른 글꼴만 써라.
    • 중앙 정렬은 꼭 필요할 때만 사용하라
    • 글꼴 선택은 최대한 심플하게하라.
    • 글자 리사이징에 대한 대비를 하자.
    • 큰 블럭 글자는 ‘serif’ 글꼴을 쓴다.
    • 적은 양의 글자는 ‘sans serif’ 글꼴을 쓴다.
    • 한 화면에서 대비 되는 글꼴을 써라.(Use contrasting font-families on the same screen.)
    • 한 화면에서 글꼴의 특성을 다양하게 쓰고 싶으면, 한 글꼴로 해라. (글꼴 특성이란, 이텔리체, 볼드체, 사이즈, 색깔등을 말한다.)

Screen Shot 2014-03-21 at 12.25.38 PM

Screen Shot 2014-03-21 at 12.25.47 PM

내용에 집중하라

  • 불필요한 디테일은 삭제하라

  • 크롬을 강조하지 마라 (Navigation bar, tool bar, and etc.)

Screen Shot 2014-03-21 at 12.27.32 PM

  • 심플한 배경

  • 필요하면 크롬을 감춰라

Screen Shot 2014-03-21 at 12.28.30 PM

  • UI 요소를 간단히하라

  • 보더 없는 버튼

  • 색깔을 사용하여 터치 가능한지 않한지를 구분하라

  • 현실적인 3D 디자인을 줄여라

Screen Shot 2014-03-21 at 2.12.02 PM

 

컨텐츠에 집중하기

  • 전체 화면을 써라

  • 컨텐츠도 디자인의 일부이다

Screen Shot 2014-03-21 at 2.14.20 PM

  • 시각적으로 재미있게 만들라.

Screen Shot 2014-03-21 at 2.17.03 PM

 

 

마치며…

이 글을 통해 그동안 느낌으로만 디자인 감각에 충실했던 개발자들에게 기본적인 개념을 심어주었으면 좋겠다. 마지막으로 학부 시절 때 들었던 미술 교양 강사님의 말이 생각을 전하며 마무리를 하고 싶어졌다.

‘디자인 감각은 선천적인 것이 아니다. 절대적으로 후천적으로 개발되는 것이다. 그럼 어떻게 해야 감각이 생길까? 많이 봐라!’

옷을 잘 입는 사람이나 디자인을 잘한다고 하는 사람들이 입을 모아서 하는 말이다. 앱을 많이 써보고 어떤 부분에서 이상한지, 어떤 부분에서 느낌이 좋은지 그냥 지나치지 말고 머리로 한번 더 생각을 해보자. 개발자들의 특성상 앱이나 서비스를 보게 되면 어떻게 작동할 것 같은지 혹은 어떤 기술을 썼는지에 관심을 더 갖게 되어 있다. 하지만 우리도 이젠 디자인이라는 포장 및에 모습만 보려하지말고 어떤 포장을 썼는지에도 관심을 가지고 더욱 User-Friendly한 개발자가 되어야겠다.