JavaScript에서 불변성이 중요한 이유는 무엇입니까?
현재 React JS 및 React Native 프레임 워크 에서 작업하고 있습니다. 절반의 길에서 나는 Facebook의 Flux 및 Redux 구현에 대해 읽을 때 Immutability 또는 Immutable-JS 라이브러리를 발견했습니다 .
문제는 왜 불변성이 그렇게 중요한가? 객체를 돌연변이시키는 데 무엇이 잘못 되었습니까? 간단하지 않습니까?
예를 들어, 시작 화면이 뉴스 헤드 라인의 목록보기 인 간단한 뉴스 리더 앱을 고려하십시오 .
처음 에 값을 가진 객체 배열을 설정하면 조작 할 수 없습니다. 그것이 불변 원리가 말한 것입니다. (잘못되면 바로 잡으십시오.)하지만 업데이트해야 할 새 뉴스 개체가 있으면 어떻게합니까? 일반적인 경우에는 객체를 배열에 추가했을 수 있습니다. 이 경우 어떻게 달성합니까? 상점을 삭제하고 다시 만드시겠습니까? 배열에 객체를 추가하는 것이 비용이 덜 드는 작업입니까?
나는 최근에 같은 주제를 연구하고 있습니다. 귀하의 질문에 답변하고 지금까지 배운 내용을 공유하기 위해 최선을 다하겠습니다.
문제는 왜 불변성이 그렇게 중요한가? 객체를 돌연변이시키는 데 무엇이 잘못 되었습니까? 간단하지 않습니까?
기본적으로 불변성은 예측 가능성, 성능을 간접적으로 증가시키고 돌연변이 추적을 허용한다는 사실에 달려 있습니다.
예측 가능성
돌연변이는 변화를 숨겨 (예기치 않은) 부작용을 일으켜 불쾌한 버그를 일으킬 수 있습니다. 불변성을 적용하면 응용 프로그램 아키텍처와 정신 모델을 단순하게 유지할 수 있으므로 응용 프로그램에 대한 추론이 쉬워집니다.
공연
불변 객체에 값을 추가한다는 것은 기존 값을 복사해야하는 곳에 새로운 인스턴스를 생성해야하고 메모리를 소모하는 새로운 객체에 새로운 값을 추가해야한다는 것을 의미하지만 불변 객체는 메모리를 줄이기 위해 구조적 공유를 사용할 수 있습니다 간접비.
모든 업데이트는 새로운 값을 반환하지만 내부 구조는 공유되어 메모리 사용량 (및 GC 스 래싱)을 크게 줄입니다. 즉, 1000 개의 요소가있는 벡터에 추가하면 실제로 1001 개의 요소로 새 벡터를 만들지 않습니다. 내부적으로 몇 개의 작은 개체 만 할당되어있을 가능성이 높습니다.
돌연변이 추적
메모리 사용 감소 외에도 불변성을 통해 참조 및 값 평등을 사용하여 응용 프로그램을 최적화 할 수 있습니다. 이렇게하면 변경된 것이 있는지 쉽게 알 수 있습니다. 예를 들어 반응 구성 요소의 상태 변경. shouldComponentUpdate
상태 객체를 비교하고 불필요한 렌더링을 방지하여 상태가 동일한 지 확인 하는 데 사용할 수 있습니다 . 이에 대한 자세한 내용은 여기를 참조 하십시오 .
추가 자료 :
처음에 값을 가진 객체 배열을 설정하면. 조작 할 수 없습니다. 그것이 불변성 원리가 말하는 것입니다. (내가 틀렸다면 정정하십시오). 그러나 업데이트해야 할 새 뉴스 개체가 있으면 어떻게합니까? 일반적인 경우에는 객체를 배열에 추가했을 수 있습니다. 이 경우 어떻게 달성합니까? 상점을 삭제하고 다시 만드시겠습니까? 배열에 객체를 추가하는 것이 비용이 덜 드는 작업입니까?
네 맞습니다. 애플리케이션에서 이것을 구현하는 방법에 대해 혼란 스러우면 핵심 개념에 익숙해지기 위해 redux 가이를 수행 하는 방법을 살펴 보는 것이 좋습니다 .
나는 불변성을 포용하기 때문에 Redux를 예로 사용하고 싶습니다. 여기에는 하나의 불변 상태 트리 (이라고 함 store
)가 있으며, 모든 상태 변경은 명시 적으로 조치와 함께 이전 상태를 수락하고 애플리케이션의 다음 상태를 반환하는 감속기에 의해 처리되는 조치를 디스패치함으로써 명시 적으로 나타납니다. . 핵심 원칙에 대한 자세한 내용은 여기를 참조하십시오 .
egghead.io 에는 redux의 저자 인 Dan Abramov가 이러한 원칙을 다음과 같이 설명 하는 훌륭한 redux 과정 이 있습니다 (시나리오에 더 적합하도록 코드를 약간 수정했습니다).
import React from 'react';
import ReactDOM from 'react-dom';
// Reducer.
const news = (state=[], action) => {
switch(action.type) {
case 'ADD_NEWS_ITEM': {
return [ ...state, action.newsItem ];
}
default: {
return state;
}
}
};
// Store.
const createStore = (reducer) => {
let state;
let listeners = [];
const subscribe = (listener) => {
listeners.push(listener);
return () => {
listeners = listeners.filter(cb => cb !== listener);
};
};
const getState = () => state;
const dispatch = (action) => {
state = reducer(state, action);
listeners.forEach( cb => cb() );
};
dispatch({});
return { subscribe, getState, dispatch };
};
// Initialize store with reducer.
const store = createStore(news);
// Component.
const News = React.createClass({
onAddNewsItem() {
const { newsTitle } = this.refs;
store.dispatch({
type: 'ADD_NEWS_ITEM',
newsItem: { title: newsTitle.value }
});
},
render() {
const { news } = this.props;
return (
<div>
<input ref="newsTitle" />
<button onClick={ this.onAddNewsItem }>add</button>
<ul>
{ news.map( ({ title }) => <li>{ title }</li>) }
</ul>
</div>
);
}
});
// Handler that will execute when the store dispatches.
const render = () => {
ReactDOM.render(
<News news={ store.getState() } />,
document.getElementById('news')
);
};
// Entry point.
store.subscribe(render);
render();
또한,이 비디오는 다음에 대해 불변성을 달성하는 방법을 자세히 보여줍니다.
불변성의 모순 된 견해
짧은 대답 : 불변성은 JavaScript의 필요성보다 패션 트렌드입니다. 일반적으로 잘못된 이유가 있지만 유용 할 때 몇 가지 좁은 경우가 있습니다 (대부분 React / Redux).
긴 대답 : 아래를 읽으십시오.
왜 자바 스크립트에서 불변성이 그렇게 중요하거나 필요한가?
글쎄, 당신이 물어봐서 기뻐요!
얼마 전에 Dan Abramov 라는 재능있는 사람 은 순수한 기능과 불변성을 사용하는 Redux 라는 자바 스크립트 상태 관리 라이브러리를 작성했습니다 . 또한 아이디어를 이해하고 판매하기 쉽게 만드는 멋진 동영상 을 만들었습니다.
타이밍이 완벽했습니다. Angular 의 참신함 은 희미 해졌고 JavaScript 세계는 적절한 수준의 시원함을 가진 최신 것을 고칠 준비가되었습니다.이 라이브러리는 혁신적 일뿐 만 아니라 다른 Silicon Valley 강국에 의해 통제되고 있는 React 와 완벽하게 슬롯되었습니다 .
슬프게도 패션은 JavaScript 세계에서 지배합니다. 이제 아브라모프는 반신으로 찬사를 받고 있으며, 필사자 들만이 불변성 의 Dao에 자신을 맡겨야합니다.
객체를 돌연변이시키는 데 무엇이 잘못 되었습니까?
아무것도!
실제로 프로그래머는 변형 할 객체가있는 한 객체를 변형했습니다. 다시 말해 50 년 이상의 응용 프로그램 개발입니다.
왜 문제가 복잡합니까? 당신이 물건 cat
을 가지고 죽을 때, 당신은 정말로 cat
변화를 추적하기 위해 1 초가 필요 합니까? 대부분의 사람들은 그냥 말하고 cat.isDead = true
끝낼 것입니다.
(개체를 돌연변이시키는) 것이 일을 단순하게하지 않습니까?
예! .. 물론 그렇습니다!
특히 JavaScript에서는 실제로 데이터베이스와 같이 다른 곳에서 유지 관리되는 일부 상태의 뷰를 렌더링하는 데 가장 유용합니다.
업데이트해야 할 새 뉴스 개체가 있으면 어떻게합니까? ...이 경우 어떻게 달성합니까? 상점을 삭제하고 다시 만드시겠습니까? 배열에 객체를 추가하는 것이 비용이 덜 드는 작업입니까?
글쎄, 전통적인 접근 방식으로 News
객체를 업데이트하여 객체의 메모리 내 표현이 변경되고 사용자에게 표시되는보기가 변경 될 수 있습니다 ...
아니면 ...
섹시한 FP / Immutability 접근 방식을 시도하고 모든 변경 사항을 추적하는 배열에News
객체 의 변경 사항을 추가하여 배열 을 반복하고 올바른 상태 표현이 무엇인지 파악할 수 있습니다 (푸우!).
나는 여기에 무엇이 있는지 배우려고합니다. 나를 계몽하십시오 :)
패션이왔다 갔다. 고양이를 피부에 바르는 방법에는 여러 가지가 있습니다.
끊임없이 변화하는 프로그래밍 패러다임의 혼란을 겪게되어 유감입니다. 그러나 안녕하세요, 클럽에 오신 것을 환영합니다 !!
이제 불변성과 관련하여 기억해야 할 몇 가지 중요한 사항이 있으며, 순진한 사람 만이 할 수있는 열렬한 강도로 이러한 것들을 얻을 수 있습니다.
1) 다중 스레드 환경에서 경쟁 조건 을 피하기 위해 불변성은 훌륭 합니다 .
다중 스레드 환경 (C ++, Java 및 C #과 같은)은 둘 이상의 스레드가 객체를 변경하려고 할 때 객체를 잠그는 관행에 유죄입니다. 이것은 성능에는 좋지 않지만 데이터 손상의 대안보다 낫습니다. 그러나 모든 것을 불변으로 만드는 것만 큼 좋지는 않습니다 (주님 Haskell을 칭찬하십시오!).
하지만 그렇습니다! JavaScript에서는 항상 단일 스레드에서 작동합니다 . 웹 워커조차 (각각 별도의 컨텍스트 내에서 실행 ). 따라서 실행 컨텍스트 내 에서 스레드 관련 경쟁 조건을 가질 수 없으므로 (모든 사랑스러운 전역 변수 및 클로저) 불변성을 선호하는 요점은 창 밖으로 나옵니다.
(가, 그런 말을 데 입니다 메인 스레드에서 개체 하구에 대한 어떤 기대가없는 것이 오 웹 노동자, 순수한 기능을 사용하는 장점은.)
2) 불변성은 앱 상태에서 경쟁 조건을 피할 수 있습니다.
그리고 여기에 문제의 진정한 요점이 있습니다. 대부분의 (React) 개발자는 불변성과 FP가 어떻게 든 마법을 사용하여 응용 프로그램의 상태를 예측할 수 있다고 말할 것입니다.
물론 이것이 데이터베이스의 경쟁 조건을 피하고 모든 브라우저의 모든 사용자 를 조정 해야하며 WebSockets 와 같은 백엔드 푸시 기술이 필요 하다는 것을 의미하지는 않습니다 ( 아래에 더 자세히 설명) 앱을 실행하는 모든 사람에게 변경 사항을 브로드 캐스트합니다.
이 혼란스러운 주장은 단순히 브라우저 내에서 작동하는 단일 사용자에 의해 정의 된 상태 객체에 할당 된 최신 값이 예측 가능하다는 것을 의미합니다. 전혀 진전이 없습니다. 상태를 추적하기 위해 평범한 오래된 변이 변수를 사용할 수 있었고 액세스 할 때마다 최신 정보를 다루고 있음을 알았으므로 React / Redux 이외의 다른 작업에서는 작동합니다.
왜? React는 특별하기 때문에 .. 구성 요소 상태는 제어 할 수없는 이벤트 체인을 통해 관리되며 상태를 직접 변경하지 않는 것을 기억 해야 합니다 . React 과대 광고가 단점을 섹시한 패션으로 바꾸어 놓은 것처럼 이것은 PR 관점에서 놀랍게 처리되었습니다. 패션을 제외하고, 나는 그것이 무엇인지에 대한 불변성을 보길 원합니다. 즉, 프레임 워크 선택이 상태를 직관적으로 처리하지 않을 때 격차를 줄이는 도구입니다.
3) 경쟁 조건은 엄청나게 나쁘다.
글쎄, 당신이 React를 사용한다면 그럴 수 있습니다. 그러나 다른 프레임 워크를 선택하면 드물게 나타납니다.
게다가, 당신은 일반적으로 다루어야 할 훨씬 더 큰 문제 가 있습니다 ... 의존성 지옥 같은 문제. 부풀린 코드베이스처럼. CSS 가로 드되지 않는 것처럼. 느린 빌드 프로세스 또는 반복을 거의 불가능하게하는 모 놀리 식 백엔드에 빠지는 것처럼. 미숙 한 개발자들과 마찬가지로 무슨 일이 일어나고 있는지 이해하지 못하고 엉망으로 만듭니다.
당신은 알고있다. 현실. 근데 누가 신경써?
4) 불변성은 참조 유형 을 사용하여 모든 상태 변경 추적의 성능 영향을 줄입니다.
진지하게, 상태가 바뀔 때마다 물건을 복사하려는 경우 현명한 지 확인하는 것이 좋습니다.
5) 불변성은 물건을 취소 할 수 있습니다 .
왜냐하면 .. 이것은 프로젝트 관리자가 요구하는 최고의 기능입니다. 맞습니까?
6) 불변 상태는 WebSocket과 함께 멋진 잠재력을 가지고 있습니다.
마지막으로, 상태 델타의 누적은 WebSocket과 함께 매우 매력적인 사례를 만들어 불변의 이벤트 흐름으로 상태를 쉽게 사용할 수 있습니다 ...
페니가이 개념을 포기하면 ( 최신 견해를 나타내는 조잡한 기록이 아니라 사건의 흐름 이된다) 불변의 세계는 거주하기에 마법의 장소가된다. 시간 을 초월 하는 이벤트 기반의 경이와 가능성 의 땅 . 그리고 완료되면 바로이 확실히 실시간 EASI 애플 리케이션을 만들 수 있습니다 어 달성하기를, 당신은 단지 그들이 본 자신의 표현을 구축하고 공동 흐름에 자신의 변화를 다시 쓸 수 있도록 관심있는 모든 사람에게 사건의 흐름을 방송.
그러나 어떤 시점에서 당신은 깨어나 모든 경이와 마법이 무료로 오지 않는다는 것을 깨달았습니다. 열성적인 동료 들과는 달리, 이해 관계자 (즉, 돈을 지불하는 사람들)는 패션과 판매 할 수있는 제품을 만들기 위해 지불하는 돈에 대해 거의 관심이 없습니다. 결론은 불변의 코드를 작성하기가 어렵고 깨지기 쉬우 며, 지원할 백엔드가 없다면 불변의 프론트 엔드를 갖는 것이 거의 없다는 것입니다. WebSockets와 같은 푸시 기술을 통해 이벤트를 게시하고 소비해야한다는 사실을 이해 관계자에게 마침내 설득 하면 프로덕션 환경에서 확장 해야 할 고통이 무엇인지 알게됩니다 .
이제 몇 가지 조언을 받아들이도록 선택해야합니다.
FP / Immutability를 사용하여 JavaScript를 작성하는 선택은 또한 응용 프로그램 코드 기반을 더 크고 복잡하고 관리하기 어렵게 만드는 선택입니다. 이 방법을 Redux 감속기로 제한하는 것에 대해 강력하게 주장합니다. 다시 말해 : Just It It Simple ™입니다. 대부분의 경우 더 나아질 것입니다. 그리고 당신이없는 곳 에서는 순전히 기능적인 프론트 엔드를 구축하고 일을 호출하는 대신 (전체) 앱을 통해 흐르는 불변의 데이터 의 이점 을 얻는 데 중점을 둡니다 .
지금, 당신이 당신의 일에서 선택을 할 수있을만큼 운이 좋으면, 당신의 지혜를 시도하고 사용하고 당신 에게 돈을 지불하는 사람이 옳은 일을하십시오 . 당신의 경험, 장, 또는 당신의 주위에 무슨 일이 있었는지에 근거 할 수 있습니다. (모든 사람들이 React / Redux를 사용하고 있다면 당신의 작업을 계속할 수있는 자료를 더 쉽게 찾을 수 있다는 유효한 주장이 있습니다) Resume Driven Development 또는 Hype Driven Development 접근법을 시도 할 수 있습니다 . 그들은 더 당신의 일이 될 수 있습니다.
즉, 일이 불변성에 대해 말했다 수는 있다는 것입니다 것입니다 다음 열풍 주위에 제공 적어도 때까지하는 당신이 이동 드리겠습니다 포인트, 동료와 당신이 유행합니다.
나는 이것을 내 블로그 => JavaScript의 불변성 : A Contrarian View에 기사로 추가했다 . 가슴에서 내리고 싶은 강한 감정이 있다면 자유롭게 답장을 보내십시오.).
문제는 왜 불변성이 그렇게 중요한가? 객체를 돌연변이시키는 데 무엇이 잘못 되었습니까? 간단하지 않습니까?
사실, 그 반대는 사실입니다 : 가변성은 적어도 장기적으로는 일을 더 복잡하게 만듭니다. 예, 원하는 곳에서 원하는대로 변경할 수 있기 때문에 초기 코딩이 더 쉬워 지지만 프로그램이 커질수록 문제가됩니다. 값이 변경되면 무엇이 바뀌 었습니까?
모든 것을 불변으로 만들면 더 이상 놀랍게도 데이터를 변경할 수 없습니다. 함수에 값을 전달하면 해당 함수에서 값을 변경할 수 없다는 것을 알고 있습니다.
간단히 말해 : 불변의 값을 사용하면 코드에 대해 추론하기가 매우 쉽습니다. 모든 사람이 고유 한 * 데이터 사본을 얻으므로 데이터를 혼동하지 않고 코드의 다른 부분을 깰 수 없습니다. 이것이 멀티 스레드 환경에서 얼마나 쉽게 작업 할 수 있는지 상상해보십시오!
참고 1 : 수행중인 작업에 따라 불변성에 대한 잠재적 성능 비용이 있지만 Immutable.js와 같은 것들이 최대한 최적화됩니다.
참고 2 : 확실하지 않은 상황에서 Immutable.js와 ES6 const
은 매우 다른 의미를 갖습니다 .
일반적인 경우에는 객체를 배열에 추가했을 수 있습니다. 이 경우 어떻게 달성합니까? 상점을 삭제하고 다시 만드시겠습니까? 배열에 객체를 추가하는 것이 비용이 덜 드는 작업입니까? 추신 : 예제가 불변성을 설명하는 올바른 방법이 아닌 경우 올바른 실제 예가 무엇인지 알려주십시오.
예, 귀하의 뉴스 사례는 완벽하고 귀하의 추론은 옳습니다. 기존 목록을 수정할 수 없으므로 새로운 목록을 작성해야합니다.
var originalItems = Immutable.List.of(1, 2, 3);
var newItems = originalItems.push(4, 5, 6);
다른 답변은 괜찮지 만 실제 사용 사례에 대한 귀하의 질문을 해결하기 위해 (다른 답변에 대한 의견에서) 잠시 동안 실행중인 코드를 벗어나서 바로 코 아래에서 유비쿼터스 답변을 볼 수 있습니다 : git . 커밋을 푸시 할 때마다 리포지토리의 데이터 를 덮어 쓰면 어떻게됩니까?
이제 우리는 불변 컬렉션이 직면하는 문제 중 하나 인 메모리 팽창에 직면 해 있습니다. Git은 변경 할 때마다 단순히 파일의 새로운 사본을 만들지 않을만큼 똑똑 하여 diff를 추적합니다 .
나는 git의 내부 작업에 대해 많이 알지 못하지만 참조하는 라이브러리의 구조와 유사한 전략을 사용한다고 가정 할 수 있습니다 : 구조 공유. 라이브러리는 시도 또는 다른 트리를 사용하여 다른 노드 만 추적합니다.
대수 시간으로 작동하는 잘 알려진 트리 연산 알고리즘이 있기 때문에이 전략은 메모리 내 데이터 구조에 대해서도 합리적으로 수행 됩니다.
또 다른 유스 케이스 : webapp에서 실행 취소 버튼을 원한다고 가정하십시오. 데이터를 변경할 수없는 표현으로 구현하는 것은 비교적 사소한 일입니다. 그러나 돌연변이에 의존한다면 세계 상태를 캐싱하고 원자 업데이트를하는 것에 대해 걱정해야한다는 의미입니다.
요컨대, 런타임 성능과 학습 곡선의 불변성에 대한 대가가 있습니다. 그러나 숙련 된 프로그래머라면 디버깅 시간이 코드 작성 시간보다 몇 배나 크다는 것을 알게 될 것입니다. 또한 런타임 성능에 대한 약간의 히트는 사용자가 견뎌 낼 필요가없는 상태 관련 버그로 인해 중요 할 수 있습니다.
JavaScript에서 불변성이 중요한 이유는 무엇입니까?
불변성은 다른 상황에서 추적 될 수 있지만 가장 중요한 것은 응용 프로그램 상태 및 응용 프로그램 UI에 대해 추적하는 것입니다.
JavaScript Redux 패턴을 매우 트렌디하고 현대적인 접근 방식으로 생각할 것입니다.
UI의 경우 예측 가능 해야합니다 . 이 경우 예측 가능합니다 UI = f(application state)
.
Applications (in JavaScript) do change the state via actions implemented using the reducer function.
The reducer function simply takes the action and the old state and returns the new state, keeping the old state intact.
new state = r(current state, action)
The benefit is: you time-travel the states since all the state objects are saved, and you can render the app in any state since UI = f(state)
So you can undo/redo easily.
Happens to be creating all these states can still be memory efficient, an analogy with Git is great, and we have the similar analogy in Linux OS with symbolic links (based on the inodes).
The question is, why is immutability so important? What is wrong in mutating objects? Doesn't it make things simple?
About mutability
기술적 인 관점에서 볼 때 가변성에는 문제가 없습니다. 빠르며 메모리를 재사용하고 있습니다. 개발자는 처음부터 기억합니다. 가변성 사용에 문제가 있으며이 사용으로 인해 문제가 발생할 수 있습니다.
객체가 어떤 것과 공유되지 않으면, 예를 들어 함수의 범위 내에 존재하고 외부에 노출되지 않으면 불변성의 이점을보기가 어렵습니다. 실제로이 경우에는 불변 인 것이 이치에 맞지 않습니다. 불변의 의미는 무언가가 공유 될 때 시작됩니다.
돌연변이 성 두통
가변적 인 공유 구조는 많은 함정을 쉽게 만들 수 있습니다. 참조에 액세스 할 수있는 코드 부분의 변경 사항은이 참조를 볼 수있는 다른 부분에 영향을줍니다. 이러한 충격은 서로 다른 모듈을 인식하지 않아도 모든 부품을 연결합니다. 하나의 함수에서 돌연변이는 앱의 완전히 다른 부분에서 충돌을 일으킬 수 있습니다. 그러한 것은 나쁜 부작용입니다.
다음으로 돌연변이 문제는 종종 손상 상태입니다. 중간에 돌연변이 절차가 실패하고 일부 필드가 수정되고 일부는 수정되지 않은 경우 손상된 상태가 발생할 수 있습니다.
또한 돌연변이로 인해 변화를 추적하기가 어렵습니다. 간단한 참조 검사는 차이점을 보여주지 않고 어떤 심층 검사가 변경되었는지를 알고 있습니다. 또한 변경 사항을 모니터링하려면 관찰 가능한 일부 패턴을 도입해야합니다.
Finally, mutation is reason of the trust deficit. How you can be sure that some structure has wanted value, if it can be mutated.
const car = { brand: 'Ferrari' };
doSomething(car);
console.log(car); // { brand: 'Fiat' }
As above example shows, passing mutable structure always can finish by having different structure. Function doSomething is mutating the attribute given from outside. No trust for the code, you really don't know what you have and what you will have. All these problems take place because: Mutable structures are representing pointers to the memory.
Immutability is about values
Immutability means that change is not done on the same object,structure, but change is represented in new one. And this is because reference represents value not only memory pointer. Every change creates new value and doesn't touch the old one. Such clear rules gives back the trust and code predictability. Functions are safe to use because instead of mutation, they deal with own versions with own values.
Using values instead of memory containers gives certainty that every object represents specific unchangeable value and it is safe to use it.
Immutable structures are representing values.
I am diving even more into the subject in medium article - https://medium.com/@macsikora/the-state-of-immutability-169d2cd11310
Another benefit of Immutability in Javascript is that it reduces Temporal Coupling, which has substantial benefits for design generally. Consider the interface of an object with two methods:
class Foo {
baz() {
// ....
}
bar() {
// ....
}
}
const f = new Foo();
It may be the case that a call to baz()
is required to get the object in a valid state for a call to bar()
to work correctly. But how do you know this?
f.baz();
f.bar(); // this is ok
f.bar();
f.baz(); // this blows up
To figure it out you need to scrutinise the class internals because it is not immediately apparent from examining the public interface. This problem can explode in a large codebase with lots of mutable state and classes.
If Foo
is immutable then this is no longer a problem. It is safe to assume we can call baz
or bar
in any order because the inner state of the class cannot change.
Once upon a time, there was a problem with data synchronization between threads. This problem was a great pain, there were 10+ solutions. Some people tried to solve it radically. It was a place where functional programming was born. It is just like Marxism. I couldn't understand how Dan Abramov sold this idea into JS, because it is single threaded. He is a genius.
I can give a small example. There is an attribute __attribute__((pure))
in gcc. Compilers tries to solve whether your function is pure or not if you won't declear it specially. Your function can be pure even your state is mutable. Immutability is just a one of 100+ ways to guarantee that you function will be pure. Actually 95% of your functions will be pure.
You shouldn't use any limitations (like immutability) if you actually don't have a serious reason. If you want to "Undo" some state, you can create transactions. If you want to simplify communications you can send events with immutable data. It is up to you.
I am writing this message from post marxism republic. I am sure that radicalization of any idea is a wrong way.
A Different Take...
My other answer addresses the question from a very practical standpoint, and I still like it. I've decided to add this as another answer rather than an addendum to that one because it is a boring philosophical rant which hopefully also answers the question, but doesn't really fit with my existing answer.
TL;DR
Even in small projects immutability can be useful, but don't assume that because it exists it's meant for you.
Much, much longer answer
NOTE: for the purpose of this answer I'm using the word 'discipline' to mean self-denial for some benefit.
This is similar in form to another question: "Should I use Typescript? Why are types so important in JavaScript?". It has a similar answer too. Consider the following scenario:
You are the sole author and maintainer of a JavaScript/CSS/HTML codebase of some 5000 lines. Your semi-technical boss reads something about Typescript-as-the-new-hotness and suggests that we may want to move to it but leaves the decision to you. So you read about it, play with it, etc.
So now you have a choice to make, do you move to Typescript?
Typescript has some compelling advantages: intellisense, catching errors early, specifying your APIs upfront, ease of fixing things when refactoring breaks them, fewer tests. Typescript also has some costs: certain very natural and correct JavaScript idioms can be tricky to model in it's not-especially-powerful type system, annotations grow the LoC, time and effort of rewriting existing codebase, extra step in the build pipeline, etc. More fundamentally, it carves out a subset of possible correct JavaScript programs in exchange for the promise that your code is more likely to be correct. It's arbitrarily restrictive. That's the whole point: you impose some discipline that limits you (hopefully from shooting yourself in the foot).
Back to the question, rephrased in the context of the above paragraph: is it worth it?
In the scenario described, I would contend that if you are very familiar with a small-to-middling JS codebase, that the choice to use Typescript is more aesthetic than practical. And that's fine, there's nothing wrong with aesthetics, they just aren't necessarily compelling.
Scenario B:
You change jobs and are now a line-of-business programmer at Foo Corp. You're working with a team of 10 on a 90000 LoC (and counting) JavaScript/HTML/CSS codebase with a fairly complicated build pipeline involving babel, webpack, a suite of polyfills, react with various plugins, a state management system, ~20 third-party libraries, ~10 internal libraries, editor plugins like a linter with rules for in-house style guide, etc. etc.
Back when you were 5k LoC guy/girl, it just didn't matter that much. Even documentation wasn't that big a deal, even coming back to a particular portion of the code after 6 months you could figure it out easily enough. But now discipline isn't just nice but necessary. That discipline may not involve Typescript, but will likely involve some form of static analysis as well as all the other forms of coding discipline (documentation, style guide, build scripts, regression testing, CI). Discipline is no longer a luxury, it is a necessity.
All of this applied to GOTO
in 1978: your dinky little blackjack game in C could use GOTO
s and spaghetti logic and it just wasn't that big a deal to choose-your-own-adventure your way through it, but as programs got bigger and more ambitious, well, undisciplined use of GOTO
could not be sustained. And all of this applies to immutability today.
Just like static types, if you are not working on a large codebase with a team of engineers maintaining/extending it, the choice to use immutability is more aesthetic than practical: it's benefits are still there but may not outweigh the costs yet.
But as with all useful disciplines, there comes a point at which it is no longer optional. If I want to maintain a healthy weight, then discipline involving ice cream may be optional. But if I want to be a competitive athlete, my choice of whether or not to eat ice cream is subsumed by my choice of goals. If you want to change the world with software, immutability might be part of what you need to avoid it collapsing under it's own weight.
I've created a framework agnostic open source (MIT) lib for mutable (or immutable) state which can replace all those immutable storage like libs (redux, vuex etc...).
Immutable states was ugly for me because there was too much work to do (a lot of actions for simple read/write operations), code was less readable and performance for big datasets was not acceptable (whole component re-render :/ ).
With deep-state-observer I can update only one node with dot notation and use wildcards. I can also create history of the state (undo/redo/time travel) keeping just those concrete values that have been changed {path:value}
= less memory usage.
With deep-state-observer I can fine-tune things and I have grain control over component behavior so performance can be drastically improved. Code is more readable and refactoring is a lot easier - just search and replace path strings (no need to change code/logic).
I think the main reason pro immutable objects, is keeping the state of the object valid.
Suppose we have an object called arr
. This object is valid when all the items are the same letter.
// this function will change the letter in all the array
function fillWithZ(arr) {
for (var i = 0; i < arr.length; ++i) {
if (i === 4) // rare condition
return arr; // some error here
arr[i] = "Z";
}
return arr;
}
console.log(fillWithZ(["A","A","A"])) // ok, valid state
console.log(fillWithZ(["A","A","A","A","A","A"])) // bad, invalid state
경우 arr
불변의 객체가 될, 우리는 편곡이 유효한 상태에 항상 확실 할 것이다.
참고 URL : https://stackoverflow.com/questions/34385243/why-is-immutability-so-important- 또는 -needed-in-javascript
'Programing' 카테고리의 다른 글
조기 반납이 다른 것보다 느린 이유는 무엇입니까? (0) | 2020.05.24 |
---|---|
Android : 서비스에서 현재 포 그라운드 활동을 얻으려면 어떻게해야합니까? (0) | 2020.05.24 |
Spring MVC와 Spring Boot의 차이점 (0) | 2020.05.24 |
Firefox에서 선택 요소에서 화살표를 제거하는 방법 (0) | 2020.05.24 |
글꼴 크기 macvim을 변경 하시겠습니까? (0) | 2020.05.24 |