초보 팀장으로 해야 할 일

  • 근본적인 문제(원인) 파악
  • 책임간 분산(공동의 책임으로 나누자)
    • 팀원들과 문제에 대해서 상의
  • 작은 조직에서 리더십의 핵심은 '신뢰', 작은 신뢰를 지속적으로 쌓자
  • 프로젝트를 작게 나누어서 관리하자
    • 기능 별로 최소화 해서 작게 나누기
    • 시간 별로 최소화 해서 일정 잡기
  • 팀의 업무에 가시성을 부여해라
  • 팀의 핵심 스케쥴을 관리하라.
  • 프로젝트 일정을 지속적으로 리팩토링 하라
  • 협상의 기술을 늘려라. (상대방이 원하는 것을 알아내라)
  • 촉매가 되어서 팀원을 도와주어라.
  • 사람 관리가 아닌 목표를 관리하라.

 

초보 팀장이 알아야 할 관리 기법

  • 진정한 문제를 찾아라.
    도요타식 문화가 자리잡지 않은 팀이라면 가급적 '왜?' 라는 질문은 삼가하는 것이 좋다
    김성실, 왜 이렇게 보고서를 만들었어? -> 김성실, 보고서를 조금 더 개선하려면 어떻게 할까? 라고 질문하는 것이 더 좋다.
    도요타식 습관
    왜 기계가 멈춰 섰지? 과중부하가 걸려 퓨즈가 끊어졌기 때문이다.
    왜 과중부하가 발생했지? 베어링 부분이 너무 뻑뻑했기 때문이다.
    왜 뻑뻑했지? 윤활 펌프가 잘 작동하지 못했기 때문이다.
    왜 충분히 작동하지 못했지? 펌프의 축이 닳아서 덜컹거리기 때문이다.
    왜 닳았지? 여과기가 달려 있지 않아 가루가 들어갔기 때문이다.

  • 문제는 1개, 답은 n개
    팀을 이끄는 팀장으로서 익숙한 해결책을 선택하기보다, 팀원과 다양한 관점에서 해결책을 찾도록 노력해보세요.

  • 진짜 팀을 만들고 싶다면!
    책임감 나눔을 토대로 한 시너지 효과를 발휘하는 팀이 진정한 팀이다.

  • 리더십의 기초
    프로젝트 팀에서 리더십을 이루는 기초는 '신뢰'입니다. 팀장이 사소한 것 하나라도 반드시 지키려는 모습은 작은 신뢰를 쌓고, 이런 소소한 신뢰들이 모여 초대형 태풍이 몰아쳐도 팀을 보호하는 강력한 리더십 방파제가 된답니다.

  • You should have 3Sights!(Foresight, Insight, Hindsight) - 예지력, 통찰력, 회고력
    계획보다 더 중요한 것이 계획하기 입니다. 계획하기라는 행위로, 우리는 미래에 원하는 곳에 도달하기 위해 현재 부족한 것이 무엇이며, 준비해야 할 것이 어떤 것이며, 어떻게 그 곳에 도달할지 생각하는 기회를 갖습니다.
    계획이 어긋났을 경우 계획에 영향을 준 새로운 인자가 무엇인지 알아내고, 새롭게 배운 사실을 기초로 계획을 수정합니다. 이렇게 배운 경험은 배움의 노트에 기록해 둡니다. 즉, 다음 번 계획하기에 참고하기 위해서죠.

  • 정보방열기로 프로젝트 관리하기
    프로젝트 관리자는 개발자들이 자유롭게 의견을 제시하고 토론할 수 있는 분위기를 만들어 주어야 합니다. 정보방열기도 창조적인 사고를 촉진시키는 방법 가운데 하나 입니다.

  • 실수를 대하는 조직의 자세
    프로젝트에서 중요한 것은 실수한 것을 책망하기보다 실수가 반복되지 않게, 실수에서 많은 것을 배울 수 있는 분위기를 만드는 것입니다.

  • 생산성에 주목하라
    생산성을 높이려면 팀원들이 업무시간에 최대한 집중하게 하고 퇴근 이후에는 그들의 시간을 즐길수 있도록 보장해라

  • 노트를 덮고 화이트 보드를 주목해 주세요.
    팀장은 조타수 입니다. 즉, 배가 나아가는 방향을 잡는 사람입니다. 회의에서 의사결정이 제대로 되지 않는다면 팀장 여러분이 현재 키잡이 자리에 서 있는지, 노 젓는 사람 자리에 앉았는지 살펴보세요. 효과적인 회의가 되려면 전체적인 관점에서 조율하는 사회자나 촉진자가 항상 필요합니다.

  • 0.5Man Month를 경계하라!
    사람은 두 가지 일을 동시에 진행할 수 있습니다. 작업이 병렬적으로 수행되면서 성과까지 뛰어나려면 제약조건이 있습니다. 두 가지 일에 관련성이 있어야 하죠. 팀원에게 두 가지 이상의 작업을 시켜야 한다면 콘텍스트 스위칭을 고민해봐야 합니다. 이런 고민 없이 일을 시켜버린다면, 최선을 다하는 팀원에게 능력이 부족하다는 잘못된 딱지를 붙이기 때문이죠.

  • 부가가치가 적은 업무를 제거하라!
    팀원들이 반복적으로 하는 업무가 무엇인지 생각해보세요. 그런 업무들이 얼마나 많은 부가가치를 창출하는지도 분석해 보세요. 반복적이면서 부가가치도 창출하지 않는다면, 그런 업무는 최대한 자도오하해야 합니다. 개발자의 생산성을 쉽게 올리지 못하기 때문에 부가가치가 적은 업무를 줄여 팀원들이 개발에 몰입하게 해야 합니다.

  • 전체적인 관점에서 최적화하라!
    프로젝트를 하다 보면 다양한 최적화 문제에 마주칩니다. 초보 팀장이 흔히 저지르는 실수는 부분 최적화의 함정에 쉽게 빠진다는 것이죠. 항상 전체적인 관점에서 문제를 바라보도록 노력하세요. 부분 최적화의 함정에 빠지면 차라리 최적화를 하지 않았을 때보다 문제가 악화되기 때문입니다.

  • 팀장이 프로그램을 짜야 할까?
    팀장은 화학 반응에서 촉매와 비슷합니다. 촉매는 반응에 참가하지 않지만, 반응이 원하는 방향으로 빨리 일어나도록 도와주는 역할을 합니다. 팀장도 마찬가지입니다. 팀장이 프로그램을 작성할 수도 있습니다. 단, 프로그래밍이라는 행위가 팀장으로서 역할에 부합할 때 프로그래밍이 팀장의 역할에 맞는 것이죠.

  • 2프로 부족, 절대적인 혹은 상대적인 가치
    팀이 난관에 부딪히거나 위기에 직면했을 때 팀을 올바른 방향으로 나아가게 할 사람은 팀장입니다. 99퍼센트의 참담함 속에서 1퍼센트의 가능성을 찾고, 가능성에 팀의 에너지를 집중하도록 하는 것이 바로 여러분이 할 일입니다.

  • 팀장과 팀원이 충돌할 때
    팀원과 의견 충돌을 겪는다면 우선 팀원이 의도하는 바를 정확히 파악해 보세요. 여러분이 원하는 것을 다른 표현으로 말할 때가 많습니다. 반대로 팀원의 의견과 여러분의 의견이 다를 때가 있습니다. 방법에서 차이가 있을 때 팀장으로서 팀원을 설득하지 못한다면, 팀원이 하고 싶은 방법으로 일을 하도록 도와주세요. 사람들은 자신이 하고 싶은 것을 할 때 최상의 성과를 내기 때문입니다. 불행하게도 팀원의 방법으로 실패하였다고 해도 팀원을 비난하거나 조롱하지는 마세요. 대신, 팀 전체가 실수에서 무언가를 배우고 또한 실수를 반복하지 않도록 조치를 취하세요.

  • 게으른 팀장이 일정을 지연시킨다.
    좋은 관리 기법을 알고만 있는 게 아니라 실천한 사람들이죠. 자신이 옳다고 믿는 것, 팀원에게 최선이 되는 것을 항상 실천하려는 부지런함이 초보 팀장을 훌륭한 관리자로 탈바꿈시켜 줍니다.

  • 협상의 기초
    고객이 요구를 할 때 진정으로 고객이 원하는 것이 무엇인지 파악하려고 노력하세요. 고객이 반드시 반영해야 한다고 주장하거나 고객이 원하는 것이 터무니 없다고 하여도, 얼마나 시간이 걸리고, 스펙을 반영하는 데 문제가 없는지 팀원들과 의논하지 않은 상태에서 고객의 주장에(감정적으로) 반응하지 마세요. 고객의 요구 사항을 들어주어야 할 때에도 반드시 시간이 얼마나 걸리는지, 다른 문제는 없는지, 다양한 각도에서 정량적으로 정보를 수집하고 판단해야 합니다. 이런 정보들이 갖추어진 후에 스펙을 반영하는데 필요한 시간과 자원을 두고 고객과 협상하세요.

Posted by outliers
,

Posted by outliers
,

어댑터 패턴(Adapter Pattern)

정의

한 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환합니다. 어댑터를 이용하면 인터페이스 호환성 문제 때문에 같이 쓸 수 없는 클래스들을 연결해서 쓸 수 있습니다.

- 이 패턴을 이용하면 호환되지 않는 인터페이스를 사용하는 클라이언트를 그대로 활용할 수 있습니다.
- 어댑티를 새로 바뀐 인터페이스로 감쌀 때는 객체 구성(Composition)을 사용합니다.
- 클라이언트를 특정 구현이 아닌 인터페이스에 연결 시킵니다
.

// Target Interface
public interface Duck {
	public void quack();
	public void fly();
}

public class DuckAdapter implements Turkey {
	Duck duck;	
	public DuckAdapter(Duck duck) {
		this.duck = duck;
	}
	public void gobble() {
		duck.quack();
	}
	public void fly() {
		duck.fly();
	}
}
// Adaptee Interface
public interface Turkey {
	public void gobble();
	public void fly();
}

public class WildTurky implements Turkey {
	public void gobble() {
		System.out.println("Gobble gobble");
	}
	public void fly() {
		System.out.println("I'm flying a short distnace");
	}
}
// Adapter에서는 Target Interface를 구현하고, Adapter는 Adaptee Interface로 구성되어 있습니다.
// 모든 요청은 Adaptee 에게 위임 됩니다. 
public class TurkeyAdapter implements Duck {
	Turkey turkey;
	
	public TurkeyAdapter(Turkey turkey) {
		this.turkey = turkey;
	}
	public void quack() {
		turkey.gobble();
	}
	public void fly() {
		for (int i = 0; i < 5; i++) {
			turkey.fly();
		}
	}
}
// Client 에서는 target Interface 만 볼 수 있습니다.
public class Main {
	public static void main(String[] args) {
		MallardDuck duck = new MallardDuck();
		
		WildTurky turkey = new WildTurky();
		Duck turkeyAdapter = new TurkeyAdapter(turkey);
		
		System.out.println("The Turkey says.....");
		turkey.gobble();
		turkey.fly();
		
		System.out.println("\nThe Duck says.....");
		testDuck(duck);
		
		System.out.println("\nThe TurkeyAdapter says.....");
		testDuck(turkeyAdapter);
	}
	
	static void testDuck(Duck duck) {
		duck.quack();
		duck.fly();
	}
}


퍼사드 패턴(Facade Pattern)

정의

어떤 서브시스템의 일련의 인터페이스에 대한 통합된 인터페이스를 제공합니다. 퍼사드에서 고수준 인터페이스를 정의하기 때문에 서브시스템을 더 쉽게 사용할 수 있습니다.

public class Facade {
	// 우리가 사용하고자 하는 서브시스템의 모든 구성요소들이 인스턴스 변수 형태로 저장 됩니다.
	DvdPlayer dvd;
	Light light;
	Screen screen;
	
	public Facade(DvdPlayer dvd, Light light, Screen screen) {
		this.dvd = dvd;
		this.light = light;
		this.screen = screen;
	}
	// 하나하나 수동으로 작업 했던 내용들을 하나의 메소드로 순서대로 처리 합니다.
	//  각 작업은 서브시스템에 들어있는 구성요소들에게 위임 됩니다.
	public watchMove(String movie) {
		dvd.on();
		light.on();
		dvd.open();
		dvd.insert();
		screen.on();
		dvd.play();
	}
}


객체지향 원칙(디자인 원칙)
1. 애플리케이션에서 바뀌는 부분을 찾아내서 바뀌지 않는 부분으로부터 분리 시켜 캡슐화 한다.
2. 상속보다는 구성을 활용한다.
3. 구현이 아닌 인터페이스에 맞춰서 프로그래밍 한다.
4. 서로 상호작용을 하는 객체 사이에서는 가능하면 느슨하게 결합하는 디자인을 사용해야 한다.
5. 클래스는 확장에 대해서는 열려 있지만 변경에 대해서는 닫혀 있어야 한다.(OCP : Open-Closed Principle)
6. 추상화된 것에 의존하도록 만들어라. 구상 클래스에 의존하도록 만들지 않도록 한다. (의존성 뒤집기 윈칙:Dependency Inversion Principle)
7. 최소 지식 원칙(Principle of Least Knowledge) - 정말 친한 친구하고만 얘기하라.
- 시스템을 디자인할 때, 어떤 객체든 그 객체와 상호작용을 하는 클래스의 개수에 주의해야 하며, 그런 객체들과 어떤 식으로 상호작용을 하는지에도 주의를 기울여야 한다
- 최소 지식 원칙 단점 : 이 원칙을 적용하다 보면 다른 구성요소에 대한 메소드 호출을 처리하기 위해 "래퍼" 클래스를 더 만들어야 할 수도 있습니다. 그러다 보면 시스템이 더 복잡해지고, 개발 시간도 늘어나고, 성능이 떨어질 수도 있습니다.

7번 원칙에 대한 가이드 라인을 제시 합니다. 어떤 메소드에서든지 다음 네 종류의 객체의 메소드만을 호출 하면 됩니다.
1. 객체 자체
2. 메소드에 매개변수로 전달된 객체
3. 그 메소드에서 생성하거나 인스턴스를 만든 객체
4. 그 객체에 속하는 구성요소

예제)
- 원칙을 따르지 않은 경우

// station으로부터 thermometer라는 객체를 받은 다음, 그객체의 
// getTemperature() 메소드를 직접 호출 합니다.
public float getTemp() {
	Thermometer thermometer = station.getThermometer();
	return thermometer.getTemperature();
}


- 원칙을 따르는 경우
// 최소 지식 원칙을 적용하여 Station 클래스에 thermometer에 요청을 해 주는
// 메소드를 추가했습니다. 이렇게 하면 의존해야 하는 클래스의 개수를 줄일 수 있죠.
public float getTemp() {
	return station.getTemperature();
}


최소 지식 원칙을 따르면서 메소드를 호출하는 방법 예제
 
public class Car {
	// 클래스의 구성요서. 이 구성요소의 메소드는 호출해도 되죠.
	Engine engine;
	// 기타 인스턴스 변수
	
	public Car() {
		// 엔진 초기화 등을 처리
	}
	
	public void start(Key key) {
		// 새로운 객체를 생성 합니다. 이 객체의 메소드는 호출해도 됩니다.
		Doors doors = new Doors();
		// 매개변수로 전달된 객체의 메소드는 호출해도 됩니다.
		boolean authorized = key.turns();
		
		if (authorized) {
			// 이 객체의 구성요소의 메소드는 호출해도 되죠?
			engine.start();	
			// 객체 내에 있는 메소드는 호출해도 됩니다.
			updateDashboardDisplay();
			// 직접 생성하거나 인스턴스를 만든 객체의 메소드는 호출해도 됩니다.
			doors.lock();	
		}
		
	}
	
	public void updateDashboardDisplay() {
		// 디스플레이 갱신
	}
}


어댑터 패턴과 퍼사드 패턴의 차이점
어댑터 패턴은 인터페이스를 변경해서 클라이언트에서 필요로 하는 인터페이스로 적응시키기 위한 용도
퍼사드 패턴은 어떤 서브시스템에 대한 간단한 인터페이스를 제공하기 위한 용도
퍼사드는 인터페이스를 단순화 시키기 위한 용도로 쓰이는 반면, 어댑터는 인터페이스를 다른 인터페이스로 변환하기 위한 용도로 쓰입니다.

핵심 정리
- 기존 클래스를 사용하려고 하는데 인터페이스가 맞지 않으면 어댑터를 쓰면 됩니다.
- 큰 인터페이스, 또는 여러 인터페이스를 단순화시키거나 통합 시켜야 되는 경우에는 퍼사드를 쓰면 됩니다.
- 어댑터는 인터페이스를 클라이언트에서 원하는 인터페이스로 바꿔주는 역할을 합니다.
- 퍼사드는 클라이언트를 복잡한 서브시스템과 분리시켜주는 역할을 합니다.
- 어댑터를 구현할 때는 타겟 인터페이스의 크기와 구조에 따라 코딩해야 할 분량이 결정됩니다.
- 퍼사드 패턴에서는 서브시스템을 가지고 퍼사드를 만들고, 실제 작업은 서브클래스에 맡깁니다.
- 어댑터 패턴에는 객체 어댑터 패턴과 클래스 어댑터 패턴이 있다. 클래스 어댑터를 쓸려면 다중 상속 기능이 필요 합니다.
- 한 서브시트템에 퍼사드를 여러개 만들어도 됩니다.
- 어댑터는 객체를 감싸서 인터페이스를 바꾸기 위한 용도로, 데코레이터는 객체를 감싸서 새로운 행동을 추가하기 위한 용도로, 퍼사드는 일련의 객체들을 감싸서 단순화 시키기 위한 용도로 쓰입니다.
Posted by outliers
,