Scala를위한 시스템 설계 재발 명


35

많은 달이 있기 전에 나는 객체 지향 소프트웨어 엔지니어링에서 석사 학위를 받았습니다. 프로젝트 시작, 요구 사항, 분석, 설계, 아키텍처, 개발 등 모든 것을 다루었습니다. 제가 가장 좋아하는 IT 책은 객체 지향 소프트웨어 개발, 경험 기반 접근 방식 (IBM-1996)이었습니다. 당시의 진정한 전문가 그룹이 만든 책. 객체 지향 분석, 설계 및 개발 방법에 대한 제품 중심의 접근 방식을 설명합니다.

나는 게임을 디자인하고 개발했고 행복했고 내 게임의 맨 위에 있었지만 조금 어려워지기 시작했습니다. 민첩한 움직임이 오늘날의 유행이되었으며 새로운 힙 단어로 잘 알려진 반복적이고 점진적인 접근 방식으로 브랜드를 변경했습니다. 갑자기 경험이 부족한 개발자들은 마치 "요구 사항"또는 "아키텍처"라고 말했을 때 찌르기 시작했습니다. 마치 이런 것들이 마술로 대체되었습니다.

디자인과 개발은 재미를 잃어 버렸고 IT 산업 전체를 떠나게되었습니다.

그런 다음 스칼라를 발견했습니다. 먼지가 많은 길의 부드러운 비처럼 모든 것이 깨끗 해졌고, 공기가 다시 달콤 해졌고, 하드 드라이브의 작은 빛이 밤새 깊숙이 깜빡 거리면서 회사를 저의 발견의 세계로 즐겁게 만들었습니다.

나는 시스템 디자인을 좋아한다. 저는 프로그래머가 아닌 건축가입니다. 나는 분석, 디자인, 사고, 논쟁, 개선을 좋아합니다. 저는 단순하고 깨끗하며 선명한 디자인을 좋아합니다.

순수한 스칼라 솔루션은 어떻게 설계합니까?

명백한 종래의 시퀀스 다이어그램, 상호 작용 다이어그램, 객체 다이어그램 등은 명령형 및 기능적 객체 지향 시스템을 혼합하기 위해 모두 대체되거나 개선 될 수있다. 분명히 완전히 다른 무언가를위한 오프닝이 있습니다!

나는 부풀어 오른 복잡성을 찾고 있지 않습니다-나는 유연한 단순성을 찾고 있습니다. 스칼라처럼 실제로는 간단하고 쉽지만 (다르기는하지만) 요가 바지처럼 요구 사항에 맞게 확장 할 수 있습니다. 이 멋진 언어를위한 디자인 시스템이 단순하게 시작해야하며 요구 사항과 도메인에 맞게 확장 될 수 있습니다. 확실히 UML은 할 수 없습니다!

그렇다면 어떻게 순수 스칼라 시스템을 설계할까요? 잠시 동안 전체 시스템을 처음부터 새로 설계 할 수있는 고급 스러움을 느끼고 스칼라 만 사용할 것이라는 사실을 알고 있습니다. 모델의 모양은 어떻습니까? 구조와 행동을 설명하기 위해 어떤 유형의 다이어그램을 사용해야합니까? 새롭고 가벼우 며 혁신적인 도구 세트가 아닌 기존 모델링 기술을 확장하는 복잡성에 얽매이지 않고 옵션, 일치 항목, 믹스 인, 싱글 톤 개체 등을 모델링하는 방법

그러한 설계 / 프로세스 / 솔루션이 존재합니까 , 아니면 발명 할 때입니까?


+1 "요가 바지처럼 요구 사항에 맞게 확장 할 수 있습니다."
Russell

FWIW, UML과 Scala에 대해 궁금한 점이 있습니다. 또한 함수 측으로 가면 카테고리 이론 표기법을 살펴볼 가치가 있습니다. Gregory Meredith는 일반적으로 블로그에 무엇이 있는지 잘 모르겠지만 일반적으로 그것에 관한 흥미로운 프레젠테이션으로 연결됩니다.
Daniel C. Sobral

그것은 가치가 있습니다 ;-) 발굴 할 방향을 알려줍니다. 감사합니다 Daniel
Jack

가치 확인, 스칼라에 대한 "수정"UML github.com/mnn/Dia2Scala/blob/master/other/Notation.md
WeiChing 린

답변:


12

이 질문에 대한 답을 줄 수는 없지만 몇 가지 생각을하겠습니다.

저는 대학에서 컴퓨터 공학을 전공하고 있으며 지난 학기 저와 그룹은 우리의 주요 언어가 스칼라 인 대규모 소프트웨어 프로젝트를 수행했습니다. 우리는 디자인을 전통적인 방식으로 사용했습니다 : 사용 사례, 도메인 모델, 시퀀스 다이어그램, UML 클래스 다이어그램; 일반적인 하중. 그리고 당신이 이미 알고 있듯이, 그들은 적합하지 않습니다. 몇 가지 이유가 있습니다.

먼저 시퀀스 다이어그램을 고려하십시오. 시퀀스 다이어그램 의 느낌 은 안정적이고 오래 살며 반 자율적 인 배우가 서로 이야기하는 것입니다. 스칼라에서는 객체가 짧은 시간 동안 생성되는 경향이 있습니다. 또한 사례 클래스는 데이터 만 있고 코드는없는 "멍청한"객체를 권장하므로 메시지 전달 개념이 적절하지 않습니다. 그러나 시퀀스 다이어그램의 가장 어려운 과제는 퍼스트 클래스 함수를 통합 할 수있는 좋은 방법이 없다는 것입니다. 여기 또는 거기에 콜백 만 사용하는 OO 디자인에서는 작동 할 수 있지만 제어를 전송하는 주요 수단이라면 시퀀스 다이어그램에 실제 코드가 거의 반영되지 않는다는 것을 알 수 있습니다.

UML 클래스 다이어그램은 Scala에 더 적합합니다. 그렇습니다. 믹스 인은 잘 나오지 않지만, 이는 정밀 검사가 아닌 "비틀어 질"수있는 것입니다. 그러나 나는 그것이 요점을 놓칠 수 있다고 생각합니다.

스칼라가 왜 "멍청한 물건"을 가지고 있는지 다시 생각해보십시오. 메소드가없는 케이스 클래스를 작성하는 경우 :

case class NewInvite(user: User, league: League)

멤버 의 유형 에 따라 수행 할 수있는 작업에 대한 약속이 있기 때문에 메소드 가 필요 하지 않습니다 . 사실, 그들은 모든 것을 약속 합니다. 또한 프로그램 내의 모든 범위에서 범위 내의 변수와 해당 유형은 코드가 해당 시점에서 어디로 갈 수 있는지에 대한 약속을합니다.

아마도 조금 뒤로 물러서서 유형 자체에 대해 조금씩 생각하는 대신 코드가 어떤 맥락에서 살고 있는지, 그리고 프로그래머에게 약속 된 것 (그리고 결국 사용자에게 약속 된 것)으로 프로그램을 설계하십시오 ) 각각의 문맥에서 스칼라에 더 적합한 설명을 찾을 수 있습니다. 그러나 나는 단지 여기에서 추측하고 있으며, 나는이 분야에서 훨씬 더 많은 것을 탐구해야한다고 생각합니다.


"프로그래머에게 약속 된 것"-멋진 링이 있습니다. ;-)
Jack

12

UML은 80 년대 후반과 90 년대 초의 "버블 전쟁"에서 나왔습니다. 그것은 항상 디자인 방법이 아니라 표기법에 대한 타협이었습니다 . UML에 기인 한 많은 계산 결과는 비밀리에 "1 단계 : 클래스 모델 그리기"라는 디자인 방법의 결과입니다.

우리는 오래된 것들을 다시 활성화시키는 것만 큼 새로운 디자인 방법이 필요하지 않다고 제안 합니다. 책임을 정의하고 할당하는 것으로 시작한 다음 구현을 이해하고 좋은 아이디어와 표현을 따라 아이디어를 전달하십시오.

책임

CRC는 다른 OO 언어와 마찬가지로 Scala에서도 잘 작동합니다. 즉, 매우 잘 작동합니다! 행위자를 의인화하고 그들의 협력을 이해함으로써 책임 할당을 모델링하는 것은 여전히 ​​효과적입니다.

대규모에서는 여전히 개체를 사용하여 디자인해야합니다. 객체 경계는 캡슐화 경계입니다. 이러한 객체 경계 내에서 변경 가능한 상태 및 구현 세부 정보를 유지하십시오. 케이스 클래스는 훌륭한 인터페이스 객체를 생성하므로 바닐라 컬렉션 및 데이터 구조도 마찬가지입니다.

구현 이해

이러한 데이터 구조를 다른 객체가 아닌 객체 경계에 전달하면 a) 객체의 내장을 숨기는 것이 더 쉽고 b) 객체 동작의 기능적 구현이 의미가 있습니다.

프로그램의 대규모 구조를 "대규모 작은 기능 풀"로 취급하고 싶지 않을 것입니다. 대신, 시스템의 분리 된 부분들 사이의 좁은 인터페이스로 자연스럽게 끌리게됩니다. 이것들은 어쨌든 객체처럼 보이고 느껴지므로 계속해서 객체로 구현하십시오!

표현과 표기법

따라서이 디자인 구조 내에서 여전히 생각을 머리에서 꺼내 다른 사람과 공유해야합니다.

UML은 여전히 ​​시스템의 대규모 구조를 설명하는 데 유용 할 수 있습니다. 그러나 세부 수준이 낮 으면 도움이되지 않습니다.

세밀한 부분에서 글을 읽고 프로그래밍 기술을 사용해보십시오.

나는 또한 minidocs를 사용하는 것을 좋아합니다. 미니 독은 시스템 동작의 특정 측면을 설명하는 하나 또는 두 페이지의 문서입니다. 코드 근처에 앉아 업데이트해야하며 적시에 학습 할 수있을 정도로 짧아야합니다. 올바른 추상화 수준에 도달하려면 약간의 연습이 필요합니다. 유용 할 정도로 구체적이어야하지만 다음 코드 변경으로 인해 무효화 될 정도로 구체적이어야합니다.


9

순수한 스칼라 솔루션은 어떻게 설계합니까?

나는 당신 이이 질문에 대해 잘못된 각도를 취하고 있다고 생각합니다. 솔루션의 전반적인 디자인은 특정 언어와 연결되어서는 안됩니다. 오히려, 당면한 문제에 해당해야합니다. Scala의 가장 큰 장점은 디자인을 구현할 때 방해가되지 않을 정도로 유연하다는 것입니다. 반면에 Java 는 약간 혼란스러운 느낌 줄 수 있는 디자인 결정 (주로 모든 것이 동급 정신)을 시행 합니다.

설계 할 때 명시 적으로 상태를 모델링하십시오 . 불변 데이터 및 명시 적 상태는 추론하기가 훨씬 쉬운 설계로 이어집니다. 대부분의 경우 이것은 돌연변이와 명령 스타일을 사용하는 것이 더 효율적이거나 더 간단하다는 것을 알지만, 함수형 프로그래밍 솔루션으로 멋지게 변환됩니다. 스칼라는 둘 다 아주 잘 수용합니다.

스칼라가 당신의 길을 벗어나는 또 다른 이유는 당신의 요구에 맞는 DSL만드는 능력 때문 입니다. 특정 문제를 "정상"방식으로 해결하는 고유 한 작은 언어를 만든 다음 스칼라에서 간단히 구현할 수 있습니다.

요약하면, 나의 주요 요점은 "순수한 스칼라 솔루션을 디자인"하려고하지 말아야한다는 것입니다. 가장 자연스럽고 이해하기 쉬운 방식으로 솔루션을 설계해야하며, Scala는 다양한 방식으로 해당 솔루션을 구현할 수있는 매우 유연한 도구입니다. 당신이 아는 전부가 망치 일 때, 모든 문제는 못처럼 보이기 시작하므로, 당신이 이용할 수있는 다양한 접근 방법을 탐구하십시오. 가능성이 A에서 W까지 빠지지 않도록 디자인 프로세스를 X, Y 및 Z 단계로 닫으려고하지 마십시오.


4

OOD가 제한적이고 구식 인 것이 맞습니다. 그것의 주요 장점은 모든 사소한 패턴과 디자인 트릭에 대한 멋진 이름으로 잘 지정되고 의식화된다는 것입니다. 시스템 설계에 대한보다 현대적이고 합리적인 접근 방식에 필적하는 시스템은 없습니다.

디자인에 대한 의미 론적 접근 방식 인 언어 지향 프로그래밍 (Scala 커뮤니티에서 많이 사용됨)과 도메인 기반 디자인이라는 두 가지만 나열 할 수 있습니다. 후자는 좀 더 일반적인 의미 론적 디자인 접근법에 대한 지나치게 단순화되고 OOPized보기이며, OOD를 좋아하는 경우에만 즐길 수 있습니다.

또한 다른 기능 프로그래밍 커뮤니티 (예 : Haskell 및 Scheme)로부터 트릭을 배우는 것이 좋습니다. 디자인 노하우가 모두 이미 스칼라로 이전 된 것은 아닙니다.


3

문제는 순수한 스칼라 솔루션을 어떻게 설계 하는가 였습니다.

다음과 같은 답변

  1. 우리는 XYZ를 사용하기 때문에 ....
  2. 우리는 ABC를 사용하지만 그렇게 ....
  3. 우리는 XYZ를 사용하기 시작했지만 ABC가 더 나은 것으로 나타났습니다 ...

이러한 툴 세트 또는 솔루션의 일부 성숙도 또는 일반적으로 허용되는 존재를 나타냅니다.

스칼라 전용 디자인 툴 세트 를 고려하는 것이 적절한 지 여부와 관련된 의견 은 다른 문제입니다. 이것에 대한 나의 의견은 스칼라가 명령형 및 기능적 프로그래밍을 결합하는 방식에서 혁명적이라는 것입니다. 스칼라는 놀라운 개발 관행, 개념 및 원칙을 포착하므로 스칼라에 가장 적합한 솔루션을 찾을 때 서브 세트가 다른 많은 언어를 잘 지원할 수있는 솔루션을 발견하게 될 것입니다.

그러면 대체 질문에 대한 답을 알고 있다는 것이 안전합니까?

"... 하나를 발명 할 때입니까?"

그것은 될 수 있을까 ? ( ' yes '는 솔루션의 수단을 규정하지 않습니다. 기존 솔루션을 확장하거나 처음부터 생성하여 달성 할 수 있습니다. 기존 디자인 옵션에 중대한 단점이 있음을 인정합니다)

당신이 동의하지 않으면 내 대답을 투표로 환영합니다. 나는 남자처럼 받아 들일 것이다.


혁명? 왜? Lisp는 수십 년 동안 명령적이고 기능적인 접근 방식의 완벽한 조합이었습니다. 스칼라는 유형 시스템 때문에 흥미 롭습니다.
SK-logic

3
'혁명적'이 강한 강한 말이라면 사과한다. 나는 스칼라가 바퀴를 다시 발명했다는 것을 암시하지는 않는다. 사실, 스칼라는 많은 프로그래밍 언어의 장점을 잘 혼합 한 것입니다. Lisp에서도 많은 돈을 빌릴 것이라고 확신합니다. 나에게, 나는 다른 사람들을 요구하지 않는다. 스칼라 언어는 자연스럽게 나오는 방식으로 코드에 대해 생각하고 있다는 점에서 혁명적이다. 동일한 디자인 / 모델링 언어는 반드시 무료입니다. 이것이 나의 유일한 요점이었습니다-Lisp와 다른 모든 위대한 언어에 대한 공격은 없습니다.
Jack

2

언어를 구별하지 않고 Java에서 동일한 방식으로 수행합니다. 그러나 나는 기능적 (대수 하스켈 하나 또는 lisp 하나)보다는 OO 학교 출신입니다. Haskell 앱 디자인은 Scala 또는 Clojure와는 다릅니다. 또한 상태 기반 DOM으로 인해 Scala.js 앱 디자인이 다릅니다. 필수 인 앱의 상태 기반 부분과 싸우기가 어렵습니다. 시간이 지남에 따라 가능한 한 상태와 변경 가능성을 없애려고하면서 OO 방식으로 익숙해졌습니다. 내가 typelevel 또는 scalaz 팬이라면 내 앱은 아마도 다르게 보일 것입니다.

  1. 기술 스택과 클라이언트 / 서버 책임, 분산 특성과 같은 주요 디자인 결정에 대한 결정-데이터 지속성이 실제로 필요합니까? 우리의 응용 분야에 가장 적합한 것은 무엇입니까? (확실히 라이브러리 또는 프레임 워크가 아님)

  2. App.scala주요 유형 (특성 및 사례 클래스)과 역할을 정의 하는 단일 파일 부터 시작하여 AFK를 수행하는 동안 많은 고민과 생각을합니다. 하나의 파일에있는 동안 재생하기가 매우 쉽습니다. 단순한 응용 프로그램 인 경우 프로토 타입조차도 등장 할 수 있습니다. 가장 정확하고 주로 투명하고 합리적인 프로토 타입을 만드는 것보다 더 중요한 것은 없기 때문에이 단계에 많은 시간을 할애합니다. 그것은 모두 우리의 더 깊은 고민을보다 정확하게 만드는 데 도움이되며 성공 확률을 높입니다.

  3. 이제 솔루션의 정확성이 입증되고 명확한 비전이 있고 모든 잠재적 인 문제가 밝혀지면 어떤 종류의 타사 라이브러리 또는 방법론을 도입해야하는지 생각할 때입니다. 프레임 워크 나 라이브러리 몇 개만 필요한가요? 우리는이 상태가 좋은 배우를 만들 것입니까, Akka의 탄력성이 정말로 필요합니까, 아니면? 이 스트림에 Rx를 사용합니까? 대화식 기능이 10 개가 된 후에도 미쳐 가지 않도록 UI에 무엇을 사용합니까?

  4. App.scala새로운 특성과 클래스가 나타나고 커지기 때문에 파일을 여러 항목으로 나눕니다 . 그들의 인터페이스는 그들의 역할에 대해 이야기해야합니다. 이제 가능한 경우 타입 클래스와 임시 다형성을 이용하는 것에 대해 생각할 때입니다. 인터페이스를 호출하는 사람이 유연해야합니다. 요점은 일반 기능 만 구현하고 세부 정보는 호출자에게 남겨 두는 것입니다. 때로는 구현하려는 것이 Turing-complete와 유사 할 수 있으므로 호출자가 GitHub에서 기능 요청을 쌓는 대신 자체적으로 세부 사항을 구현할 수있는 방법을 제공해야합니다. 이 내용은 나중에 추가하기가 어렵습니다. 처음부터 생각해야합니다. DSL을 설계 할뿐 아니라

  5. 응용 프로그램이 커지고 디자인, 새로운 기능, 최적화, 지속성, UI, 원격 등을 견딜 준비가 되었기 때문에 디자인을 통해 생각해야합니다. 하나의 파일에 있지만 내용을 변경하는 것은 매우 쉽다는 것을 기억하십시오. 인간의 뇌는 10 개가 넘는 파일로 확산 된 후에 그것을 잃어 버리기 시작합니다. 그리고 그것은 성장하는 종양과 같습니다. 그것이 과도 공학이 시작되는 방식입니다. 내 응용 프로그램은 일종의 백본을 형성하는 몇 가지 긴 부분 함수로 끝납니다. 작업하기가 쉽다는 것을 알았습니다. Akka 배우에 감염된 것 같습니다.

  6. 핵심 기능뿐만 아니라 첫 번째 실제 기능이 있으므로 테스트 작성을 시작할 차례입니다. 왜 늦었 어? 이 기간 동안 아마도 당신은 아마도 주요한 재 작성을 겪었을 것이고 당신은 그 테스트를 유지하는데 시간을 낭비했을 것입니다. 주요 재 설계가 확실하지 않다면 테스트를 작성해서는 안됩니다. 지속적인 리팩토링을 쉽게 견딜 수있는 통합 테스트를 선호하며 실제로 개발하는 테스트에 더 많은 시간을 소비하지 않습니다. 테스트를 유지하는 데 너무 많은 시간을 소비 한 것은 몇 번이나 일어났습니다. 잠재적 인 버그를 수정하면 나쁜 테스트보다는 확실히 더 많은 돈을 지불하게됩니다. 첫 순간부터 작성된 나쁜 테스트 나 테스트는 큰 통증을 유발할 수 있습니다. 나는 확실히 TDD의 팬이 아님을 주목하십시오-IMHO 그것은 헛소리입니다.

  7. 리팩토링, 애플리케이션 디자인을 읽을 수있게하고 구성 요소 역할을 명확하게합니다. 응용 프로그램이 커짐에 따라 천재 프로그래머가 아니라면이 방법을 유지하는 방법이 없으며이 답변을 읽지 않으면 아마 그렇지 않을 것입니다 .-) 나도 아닙니다. 문제가 발생할 수 있으므로 제거해보십시오. 또한 한동안 방해했던 코드 냄새를 제거하십시오. 이 시점에서 프로젝트 관리자 (있는 경우)가 고개를 흔들기 시작합니다. 그에게 돈을 지불 할 것이라고 말하십시오.

  8. 완료, 앱이 잘 설계 되었습니까? 실제로는 다음과 같습니다. 실제로 머리 외부에서도 의미가있는 구성 요소에 잘 정의 된 역할이 있습니까? 많은 노력을 기울이지 않고 일부를 가져 와서 소스를 얻을 수 있습니까? 그들 사이에 우려가 명확하게 분리되어 있습니까? 다른 곳에서 충돌이 발생할 염려없이 새로운 기능을 추가 할 수 있습니까? 일반적으로, 문제에 대한 간단한 실용적인 해결책이 담긴 책으로 읽을 수 있어야합니다. IMHO는 좋은 디자인의 주요 신호입니다.

결국, 그것은 당신이 아마 당신의 관리자로부터 얻지 못할 힘든 일과 시간입니다. 여기에 설명 된 모든 시간, 노력, 커피, 차 및 특히 AFK를 생각합니다. 더 많이 줄수록 디자인이 좋아집니다. 응용 프로그램 설계, 상식, 실용주의, KISS, 노력, 경험에 대한 일반적인 제조법은 없습니다. 경험은 훌륭한 디자인을 의미합니다.

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