-
Notifications
You must be signed in to change notification settings - Fork 0
/
rss.xml
3789 lines (3558 loc) · 724 KB
/
rss.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Archived by Sujin]]></title><description><![CDATA[Blog posted about ...]]></description><link>https://sujin-park.github.io</link><generator>GatsbyJS</generator><lastBuildDate>Wed, 30 Mar 2022 11:07:24 GMT</lastBuildDate><item><title><![CDATA[[UX 심리학] 주의 병목 구간]]></title><description><![CDATA[…]]></description><link>https://sujin-park.github.io/user-experience/ux-psychology-attention/</link><guid isPermaLink="false">https://sujin-park.github.io/user-experience/ux-psychology-attention/</guid><pubDate>Wed, 30 Mar 2022 20:00:00 GMT</pubDate><content:encoded><aside>
📌 데이비드 에반스의 <UX 심리학 - UX 디자이너와 개발자가 알야아 할 사용자 심리의 모든 것>을 읽고 정리하였습니다.
</aside>
<h2 id="1장-중심와-시선" style="position:relative;"><a href="#1%EC%9E%A5-%EC%A4%91%EC%8B%AC%EC%99%80-%EC%8B%9C%EC%84%A0" aria-label="1장 중심와 시선 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>1장 중심와 시선</h2>
<p>당신의 비즈니스 모델이 성공하려면 당신의 아이디어를 사용자의 두뇌를 자극하는 신호로 바꿔야 한다.</p>
<p>아무리 중요한 밈이라도 인간의 해부학적 한계를 고려하여 디자인되지 않으면 사용자에게 인식되지 못하는 결과가 벌어지게 된다.</p>
<p>우리 눈의 주변시에만 잡힌다면 색상을 인지할 수도, 글자를 읽을 수도 없다.</p>
<p><strong>중심와 시선의 초점 범위가 너무 좁아서 발생하는 문제</strong></p>
<p>화상 통화는 발명 후 대중화되는데에 오랜 기간이 걸렸다. 그 이유는 서로의 눈을 정면으로 응시하려면 양쪽 모두 카메라를 보고 있어야 하지만, 이럴 때 화면에 보이는 상대방의 얼굴을 쳐다볼 수 없게 된다.</p>
<p>화상 통화는 인간의 본능에 배치되는 이런 특성으로 인해 음성 통화보다 대중화 속도가 느려질 수 밖에 없지 않았을까.</p>
<h2 id="2장-과업-지향성" style="position:relative;"><a href="#2%EC%9E%A5-%EA%B3%BC%EC%97%85-%EC%A7%80%ED%96%A5%EC%84%B1" aria-label="2장 과업 지향성 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>2장 과업 지향성</h2>
<p>밈 개발자로서 당신이 가장 먼저 해야 할 일은 사용자에게 목표가 있는지부터 알아보는 것이다.</p>
<p>사용자가 특별한 목표 없이 당신의 밈을 방문했다면, 예상치 않았거나 요청한 바 없었던 밈에도 수용적 태도를 보일 것이다. </p>
<p><strong>과업 지향적 네트워크</strong></p>
<p>집중력을 매우 요구하는 작업에 몰두하고 있을 때 뇌가 접어들게되는 상태로 두뇌의 대표적인 주의 집중 모드에 해당한다.</p>
<p>피실험자들에게 문제를 풀도록 하거나 주어진 어떤 과업을 수행하라고 하면 문제나 과업의 종류에 상관없이 과업 지향적 네트워크가 활성화된다.</p>
<p><strong>과업 회피적 네트워크</strong></p>
<p>멍하게 있는 상태로 자유로우면서도 일률적이지 않은 사고를 지원하는 두뇌 네트워크</p>
<p>과업과 과업 사이에 장비를 그대로 가동한 채 실험 대상자를 방치하면, 피실험자는 문제를 풀지 않고 장비 안에서 대기하면서 전자기장이 내는 소리를 듣게 되는데 이 때 과업 회피적 네트워크가 나타난다.</p>
<p>가장 먼저 해야 할 일은 사용자들이 과업 지향적 모드에 있는지 과업 회피적 모드에 있는지 파악하는 것이다.</p>
<p><strong>과업 지향적 사용자들은,</strong></p>
<ul>
<li>검색창을 주로 사용하는 경향을 보인다.</li>
<li>원하는 바를 얻기 위한 가장 효율적인 방법이다.</li>
<li>자신들의 목적에 방해가 되고 주의가 분산되는 것을 싫어한다.</li>
</ul>
<p><strong>과업 회피적 사용자들은,</strong></p>
<ul>
<li>사이트 전체를 훑어보는 경향이 있다.</li>
<li>몰랐던 무엇인가를 발견하기를 기대하며 사진, 링크, 아이콘들을 클릭해본다.</li>
<li>과업 지향적 사용자들보다 더 오래 머물고 많은 페이지를 방문할 수 있다.</li>
<li>힘든 작업에 참여하는 것을 싫어하고 중간에 방해받는 것을 환영했다.</li>
</ul>
<p><strong>대부분의 사용자가 과업 지향적 모드에 있을 때 해야하는 디자인 전략</strong></p>
<ul>
<li>목표 달성과 관련 없는 것은 모두 방해 요소로 인식되어 회피하게 된다.</li>
<li>마이크로소프트 오피스, 슬랙과 같은 생산성 플랫폼</li>
<li>광고가 아닌 가입을 통해 수익을 얻어야 한다.</li>
<li>사용자들이 어디를 보고 있는지 알아내서 그곳에서 미리 기다리는 전략을 세워야 한다.</li>
</ul>
<p><strong>대부분의 사용자가 과업 회피적 모드에 있을 때 해야하는 디자인 전략</strong></p>
<ul>
<li>광고를 포함하여 집중을 방해하는 어떤 것이든 환영한다.</li>
<li>사이트를 읽어 내려가는 동안 썸네일, 헤드라인, 링크가 나타나도록 한다.</li>
<li>머신 러닝을 이용하여 사용자가 이전에 방문해서 클릭했던 것과 유사한 분야의 콘텐츠를 보여준다.</li>
<li>사용자를 생각하게 하지 말라.</li>
</ul>
<h2 id="3장-주의-집중" style="position:relative;"><a href="#3%EC%9E%A5-%EC%A3%BC%EC%9D%98-%EC%A7%91%EC%A4%91" aria-label="3장 주의 집중 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>3장. 주의 집중</h2>
<p>사용자들의 목표는 최소의 주의 용량 자원을 사용하여 빠르게 페이지를 파악하는 것이고, 이를 달성하기 위해 F형 패턴으로 스캔을 한다. </p>
<p><strong>F형 스캔이란,</strong></p>
<ul>
<li>페이지의 의미를 파악하고자 하는 사용자의 목표는 보통 상단에 배치된 헤드라인에 주목함으로써 달성될 수 있다.</li>
<li>여기서 달성하지 못한 사용자는 계속해서 아래쪽으로 시선을 옮겨 가며 읽게 된다.</li>
<li>히브리어, 아랍어는 오른쪽에서 왼쪽으로 글을 쓰기 때문에 F형 패턴의 좌우가 바뀌어서 나타난다.</li>
</ul>
<p>대부분의 웹 사이트는 우측 하단이 사용자 시선의 사각지대가 된다는 점을 기억해야 한다. 중요한 링크는 가장 상단에 배치하거나 좌측 아래로 이어지는 선을 따라 배치해야 한다.</p>
<p>사용자가 정보를 찾기 위해 하는 행동은 아래와 같이 3단계로 나눌 수 있다.</p>
<ol>
<li>F형 패턴으로 사이트를 구역별로 훑어본다.</li>
<li>1단계에서 정보를 찾지 못했다면 사용자는 모든 그래픽과 아이콘을 모두 살펴보는 방식으로 정보 검색 패턴을 바꾼다.</li>
<li>2단계에서도 정보를 찾지 못했다면 페이지 내에 표시된 링크들의 단어를 모두 읽기 시작한다.</li>
</ol>
<p>그러나 3단계까지 해당 페이지에 사용자가 과연 머무를까…? 대부분의 밈은 우리에게 그 정도의 중요도를 갖고 있지 않기 때문에 사용자들은 페이지를 떠나게 될 것이다.</p>
<p>주의를 집중했을 때 돌아오는 보상이 없으면 점점 눈길을 주는 확률이 줄어드게 되는 <strong>습관화</strong> 라는 문제가 발생할 수 있다. </p>
<p>또한, 주의를 끄는 디자인 요소들을 더 많이 사용하면 주의 집중 병목 구간이 더 좁아진다.</p>
<p>소리와 애니메이션을 사용하여 더 많은 집중 반응을 끌어내려 하면 주의 집중 병목 현상이 더 심해지고 결국 그런 자극들을 무시하게 된다.</p>
<p>*미트볼: 몇 개의 알림이 있는지 보여주는 기능으로 빨간색 동그라미 안에 숫자가 표시된 디자인</p>
<p>슬랙은 @mention 이라는 기능의 유행에 큰 역할을 하였는데, 곧 사람들이 @channel 기능을 남발하기 시작했다. 이로 인해 습관화 현상이 일어났고, 슬랙은 제동을 걸기 위해 아래와 같은 창을 띄웠다.</p></content:encoded></item><item><title><![CDATA[CleanCode(클린코드) - 10장. 클래스]]></title><description><![CDATA[🔖 오늘 읽은 범위 : 1…]]></description><link>https://sujin-park.github.io/book-club/clean-code-day20/</link><guid isPermaLink="false">https://sujin-park.github.io/book-club/clean-code-day20/</guid><pubDate>Thu, 10 Feb 2022 20:00:00 GMT</pubDate><content:encoded><p>🔖 오늘 읽은 범위 : 10장 - 클래스</p>
<hr>
<br>
<h2 id="-책에서-기억하고-싶은-내용을-써보세요" style="position:relative;"><a href="#-%EC%B1%85%EC%97%90%EC%84%9C-%EA%B8%B0%EC%96%B5%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%9D%80-%EB%82%B4%EC%9A%A9%EC%9D%84-%EC%8D%A8%EB%B3%B4%EC%84%B8%EC%9A%94" aria-label=" 책에서 기억하고 싶은 내용을 써보세요 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>😃 <strong>책에서 기억하고 싶은 내용을 써보세요.</strong></h2>
<h3 id="클래스-체계" style="position:relative;"><a href="#%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%B2%B4%EA%B3%84" aria-label="클래스 체계 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>클래스 체계</h3>
<ul>
<li>
<p>클래스를 정의하는 표준 자바 관례에 따르면, 추상화 단계가 순차적으로 내려가 아래 순서로 나온다. 프로그램은 신문 기사처럼 읽힌다.</p>
<ol>
<li>
<p>변수 목록</p>
<ol>
<li>정적 공개 상수가 있다면 정적 공개 상수</li>
<li>정적 비공개 변수</li>
<li>비공개 인스턴스 변수</li>
</ol>
</li>
<li>공개 함수</li>
<li>비공개 함수는 자신을 호출하는 공개 함수 직후에</li>
</ol>
</li>
</ul>
<h3 id="클래스는-작아야-한다" style="position:relative;"><a href="#%ED%81%B4%EB%9E%98%EC%8A%A4%EB%8A%94-%EC%9E%91%EC%95%84%EC%95%BC-%ED%95%9C%EB%8B%A4" aria-label="클래스는 작아야 한다 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>클래스는 작아야 한다</h3>
<p>클래스를 만들 때 첫 번째 규칙은 크기다. 그렇다면 얼마나 작아야 하는가? <code class="language-text">클래스가 맡은 책임을 센다.</code></p>
<ul>
<li>클래스 이름은 해당 클래스 책임을 기술해야 한다. <strong>실제로 작명은 클래스 크기를 줄이는 첫 번째 관문이다.</strong></li>
<li>클래스명은 25단어 내외로 가능해야 한다.</li>
</ul>
<p><strong>단일 책임 원칙 (SRP)</strong></p>
<ul>
<li>클래스나 모듈을 변경할 이유가 하나, 단 하나뿐이어야 한다.</li>
<li>SRP 는 책임이라는 개념을 정의하며 적절한 클래스 크기를 제시한다.</li>
<li>클래스는 책임, 즉 변경할 이유가 하나여야 한다는 의미다.</li>
<li>큰 클래스 몇 개가 아니라 작은 클래스 여럿으로 이뤄진 시스템이 더 바람직하다. 작은 클래스는 각자 맡은 책임이 하나며, 변경할 이유가 하나며, 다른 작은 클래스와 협력해 시스템에 필요한 동작을 수행한다.</li>
</ul>
<p><code class="language-text">책임</code> , 즉 변경할 이유를 파악하려 애쓰다 보면 코드를 추상화하기도 쉬워진다.</p>
<p><strong>응집도</strong></p>
<ul>
<li>클래스는 인스턴스 변수 수가 작아야 한다. 각 클래스 메서드는 클래스 인스턴스 변수를 하나 이상 사용해야 한다.</li>
<li>일반적으로 메서드가 변수를 많이 사용할수록 메서드와 클래스는 응집도는 더 높다.</li>
<li>응집도가 높아질수록 변수와 메서드를 적절히 분리해 새로운 클래스 두세 개로 쪼갠다.</li>
</ul>
<h3 id="변경하기-쉬운-클래스" style="position:relative;"><a href="#%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0-%EC%89%AC%EC%9A%B4-%ED%81%B4%EB%9E%98%EC%8A%A4" aria-label="변경하기 쉬운 클래스 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>변경하기 쉬운 클래스</h3>
<ul>
<li>새 기능을 수정하거나 기존 기능을 변경할 때 건드릴 코드가 최소인 시스템 구조가 바람직하다.</li>
<li>이상적인 시스템이라면 새 기능을 추가할 때 시스템을 확장할 뿐 기존 코드를 변경하지는 않는다.</li>
<li>OCP 란 클래스는 확장에 개방적이고 수정에 폐쇠적이어야 한다는 원칙이다.</li>
</ul>
<p><strong>변경으로부터 격리</strong></p>
<ul>
<li>인터페이스와 추상 클래스를 사용해 구현이 미치는 영향을 격리한다.</li>
<li>테스트가 가능할 정도로 시스템의 결합도를 낮추면 유연성과 재사용성도 더욱 높아진다.</li>
<li>결합도가 낮다는 소리는 각 시스템 요소가 다른 요소로부터 그리고 변경으로부터 잘 격리되어 있다는 의미다.</li>
<li>
<p>결합도를 최소로 줄이면 자연스럽게 또 다른 클래스 설계 원칙 <code class="language-text">DIP</code> 를 따르는 클래스가 나온다.</p>
<ul>
<li>본질적으로 DIP는 클래스가 상세한 구현이 아니라 추상화에 의존해야 한다는 원칙이다.</li>
</ul>
</li>
</ul></content:encoded></item><item><title><![CDATA[CleanCode(클린코드) - 9장. 단위테스트]]></title><description><![CDATA[🔖 오늘 읽은 범위 : 9장 - 단위테스트 😃 책에서 기억하고 싶은 내용을 써보세요. TDD…]]></description><link>https://sujin-park.github.io/book-club/clean-code-day17/</link><guid isPermaLink="false">https://sujin-park.github.io/book-club/clean-code-day17/</guid><pubDate>Mon, 07 Feb 2022 20:00:00 GMT</pubDate><content:encoded><p>🔖 오늘 읽은 범위 : 9장 - 단위테스트</p>
<hr>
<br>
<h2 id="-책에서-기억하고-싶은-내용을-써보세요" style="position:relative;"><a href="#-%EC%B1%85%EC%97%90%EC%84%9C-%EA%B8%B0%EC%96%B5%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%9D%80-%EB%82%B4%EC%9A%A9%EC%9D%84-%EC%8D%A8%EB%B3%B4%EC%84%B8%EC%9A%94" aria-label=" 책에서 기억하고 싶은 내용을 써보세요 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>😃 <strong>책에서 기억하고 싶은 내용을 써보세요.</strong></h2>
<h3 id="tdd-법칙-세-가지" style="position:relative;"><a href="#tdd-%EB%B2%95%EC%B9%99-%EC%84%B8-%EA%B0%80%EC%A7%80" aria-label="tdd 법칙 세 가지 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><strong>TDD 법칙 세 가지</strong></h3>
<ol>
<li>실패하는 단위 테스트를 작성할 때까지 실제 코드를 작성하지 않는다.</li>
<li>컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다.</li>
<li>현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다.</li>
</ol>
<p>위 세 가지 규칙을 따르면 실제 코드를 사실상 전부 테스트하는 테스트 케이스가 나온다. 하지만 실제 코드와 맞먹을 정도로 방대한 테스트 코드는 심각한 관리 문제를 유발하기도 한다.</p>
<h3 id="깨끗한-테스트-코드-유지하기" style="position:relative;"><a href="#%EA%B9%A8%EB%81%97%ED%95%9C-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%BD%94%EB%93%9C-%EC%9C%A0%EC%A7%80%ED%95%98%EA%B8%B0" aria-label="깨끗한 테스트 코드 유지하기 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><strong>깨끗한 테스트 코드 유지하기</strong></h3>
<ul>
<li>테스트 코드는 실제 코드 못지 않게 중요하다. 테스트 코드는 사고와 설계와 주의가 필요하다. 실제 코드 못지 않게 깨끗하게 짜야 한다.</li>
<li>
<p>테스트는 유연성, 유지보수성, 재사용성을 제공한다.</p>
<ul>
<li>코드에 유연성, 유지보수성, 재사용성을 제공하는 버팀목이 바로 <code class="language-text">단위테스트</code>다.</li>
<li>테스트 코드가 지저분하면 코드를 변경하는 능력이 떨어지며 코드 구조를 개선하는 능력도 떨어진다.</li>
<li>테스트 코드가 지저분할수록 실제 코드도 지저분해진다. 결국 테스트 코드를 잃어버리고 실제 코드도 망가진다.</li>
</ul>
</li>
</ul>
<h3 id="깨끗한-코드" style="position:relative;"><a href="#%EA%B9%A8%EB%81%97%ED%95%9C-%EC%BD%94%EB%93%9C" aria-label="깨끗한 코드 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><strong>깨끗한 코드</strong></h3>
<ul>
<li>깨끗한 테스트 코드를 만들려면 <strong>가독성</strong>이 필요하다.</li>
<li>
<p>BUILD-OPERATE-CHECK 패턴이 테스트 구조에 적합하다. 각 테스트는 명확하게 세 부분으로 나눠진다.</p>
<ul>
<li>테스트 자료를 만든다.</li>
<li>테스트 자료를 조작한다.</li>
<li>조작한 결과가 올바른지 확인한다.</li>
</ul>
</li>
</ul>
<p><strong>이중 표준</strong></p>
<ul>
<li>실제 환경에서는 절대로 안 되지만 테스트 환경에서는 전혀 문제없는 방식이 있다. 대개 메모리나 CPU 효율과 관련 있는 경우다. 코드의 깨끗함과는 철저히 무관하다</li>
<li><strong>컴퓨터 자원과 메모리가 제한적일 가능성이 높지만, 테스트 환경은 자원이 제한적일 가능성이 낮다.</strong></li>
</ul>
<h3 id="테스트-당-assert-하나" style="position:relative;"><a href="#%ED%85%8C%EC%8A%A4%ED%8A%B8-%EB%8B%B9-assert-%ED%95%98%EB%82%98" aria-label="테스트 당 assert 하나 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>테스트 당 assert 하나</h3>
<ul>
<li>assert 문이 단 하나인 함수는 결론이 하나라서 코드를 이해하기 쉽고 빠르다.</li>
<li>given-when-then 이라는 관례를 사용하면 테스트 코드를 읽기가 쉬워진다.</li>
<li>
<p>테스트를 분리하면 중복되는 코드가 많아지는데, 이 때는 <code class="language-text">TEMPLATE METHOD</code> 패턴을 사용하면 중복을 제거할 수 있다.</p>
<ol>
<li>given/when 을 부모 클래스에 두고 then 을 자식 클래스에 둔다.</li>
<li>given/when 을 @Before 함수에 넣고, @Test 함수에 then 을 넣어도 된다.</li>
</ol>
</li>
</ul>
<h3 id="테스트-당-개념-하나" style="position:relative;"><a href="#%ED%85%8C%EC%8A%A4%ED%8A%B8-%EB%8B%B9-%EA%B0%9C%EB%85%90-%ED%95%98%EB%82%98" aria-label="테스트 당 개념 하나 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><strong>테스트 당 개념 하나</strong></h3>
<ul>
<li>테스트 함수마다 한 개념만 테스트하라</li>
<li>개념 당 assert 문 수를 최소로 줄여라</li>
</ul>
<h3 id="first" style="position:relative;"><a href="#first" aria-label="first permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><strong>F.I.R.S.T</strong></h3>
<p>깨끗한 테스트는 다음 다섯 가지 규칙을 따르는데, 각 규칙에서 첫 글자를 따오면 FIRST 가 된다.</p>
<ol>
<li>Fast : 테스트는 빨리 돌아야 한다. 테스트가 느리면 자주 돌릴 엄두를 못 낸다. 자주 돌리지 않으면 초반에 문제를 찾아내 고치지 못한다.</li>
<li>Independent : 각 테스트는 서로 의존하면 안 된다. 각 테스트는 독립적으로 그리고 어떤 순서로 실행해도 괜찮아야 한다.</li>
<li>Repeatable : 테스트는 어떤 환경에서도 반복 가능해야 한다.</li>
<li>Self-Validating : 테스트는 bool 값으로 결과를 내야 한다. 성공 아니면 실패다.</li>
<li>Timely : 테스트는 적시에 작성해야 한다. 단위 테스트는 테스트하려는 실제 코드를 구현하기 직전에 구현한다.</li>
</ol>
<h3 id="결론" style="position:relative;"><a href="#%EA%B2%B0%EB%A1%A0" aria-label="결론 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>결론</h3>
<p>테스트 코드는 지속적으로 깨끗하게 관리하자. 표현력을 높이고 간결하게 정리하자. 테스트 API 를 구현해 도메인 특화 언어를 만들자.</p>
<br>
<h2 id="-오늘-읽은-소감은-떠오르는-생각을-가볍게-적어보세요" style="position:relative;"><a href="#-%EC%98%A4%EB%8A%98-%EC%9D%BD%EC%9D%80-%EC%86%8C%EA%B0%90%EC%9D%80-%EB%96%A0%EC%98%A4%EB%A5%B4%EB%8A%94-%EC%83%9D%EA%B0%81%EC%9D%84-%EA%B0%80%EB%B3%8D%EA%B2%8C-%EC%A0%81%EC%96%B4%EB%B3%B4%EC%84%B8%EC%9A%94" aria-label=" 오늘 읽은 소감은 떠오르는 생각을 가볍게 적어보세요 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>🤔 <strong>오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요</strong></h2>
<ul>
<li>테스트는 유연성, 유지보수성, 재사용성을 제공한다는 것을 명심하고 테스트 코드를 작성하는 것을 필수로 해야 한다.</li>
<li>그렇지만 컴포넌트와 의존성이 강한 함수는 어떻게 테스트를 할 수 있을까? 시각적 요소를 자동화하기라는 주제로 강연이 있었는데 그걸 얼른 봐야겠다.</li>
</ul>
<br>
<p>테스트 코드는 작성하다보면 깔끔하게 작성하기가 어려울 때가 많다. 테스트 당 개념 하나를 놓치고 생각대로 작성했기에 그렇게 작성할 수 밖에 없었던게 아닐까.</p>
<p>오늘부터 다시 알고리즘을 풀면서 테스트 코드를 좀 더 깨끗하게 작성하는 방법을 익혀봐야겠다.</p>
<p>FIRST 전략 중 가장 공감이 되는 부분은 Fast 이다. 이전에 오픈소스에 기여할 때, 특정 테스트는 오래 걸려서 테스트 돌릴 때 빼고 돌리는 형태로 작업을 했었다. 작업할 때 돌리지 못한 테스트는 Pull Request 시에 테스트 할 수 있었는데 이 부분을 작업하면서 같이 돌릴 수 있으면 좀 더 많은 범위를 테스트할 수 있지 않았을까 아쉬움이 남는다. (테스트 코드 경험이 많지 않아서 작성한 예시는 매번 돌리지않아도 되는 테스트였을 수 있다.)</p>
<br>
<h2 id="-궁금한-내용이-있거나-잘-이해되지-않는-내용이-있다면-적어보세요" style="position:relative;"><a href="#-%EA%B6%81%EA%B8%88%ED%95%9C-%EB%82%B4%EC%9A%A9%EC%9D%B4-%EC%9E%88%EA%B1%B0%EB%82%98-%EC%9E%98-%EC%9D%B4%ED%95%B4%EB%90%98%EC%A7%80-%EC%95%8A%EB%8A%94-%EB%82%B4%EC%9A%A9%EC%9D%B4-%EC%9E%88%EB%8B%A4%EB%A9%B4-%EC%A0%81%EC%96%B4%EB%B3%B4%EC%84%B8%EC%9A%94" aria-label=" 궁금한 내용이 있거나 잘 이해되지 않는 내용이 있다면 적어보세요 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>🔎 <strong>궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요.</strong></h2>
<h3 id="템플릿-메소드-패턴" style="position:relative;"><a href="#%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%A9%94%EC%86%8C%EB%93%9C-%ED%8C%A8%ED%84%B4" aria-label="템플릿 메소드 패턴 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>템플릿 메소드 패턴</h3>
<p>알고리즘의 구조를 메소드에 정의하고, 하위 클래스에서 알고리즘 구조의 변경없이 알고리즘을 재정의하는 패턴</p>
<p>알고리즘이 단계별로 나누어지거나, 같은 역할을 하는 메소드이지만 여러곳에서 다른 형태로 사용이 필요한 경우 유용한 패턴이다.</p>
<p>참고: <a href="https://yaboong.github.io/design-pattern/2018/09/27/template-method-pattern/">https://yaboong.github.io/design-pattern/2018/09/27/template-method-pattern/</a></p>
<h3 id="build-operate-check-패턴" style="position:relative;"><a href="#build-operate-check-%ED%8C%A8%ED%84%B4" aria-label="build operate check 패턴 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>BUILD-OPERATE-CHECK 패턴</h3>
<p>Build - 테스트 시나리오를 준비하는 단계</p>
<p>Operate - 메서드를 실행하는 단계</p>
<p>Check - 실행된 메소드의 결과가 예상했던 것과 일치하는지 확인한다.</p>
<p><a href="https://medium.com/swlh/usual-production-patterns-applied-to-integration-tests-50a941f0b04a">https://medium.com/swlh/usual-production-patterns-applied-to-integration-tests-50a941f0b04a</a></p>
<br>
<h2 id="-소감-3줄-요약" style="position:relative;"><a href="#-%EC%86%8C%EA%B0%90-3%EC%A4%84-%EC%9A%94%EC%95%BD" aria-label=" 소감 3줄 요약 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>🔥 <strong>소감 3줄 요약</strong></h2>
<ul>
<li>깨끗한 테스트 코드를 만들려면 <strong><code class="language-text">가독성</code></strong>이 필요하다.</li>
<li>코드에 유연성, 유지보수성, 재사용성을 제공하는 버팀목이 바로 <code class="language-text">**단위테스트**</code>다.</li>
<li>TDD 법칙 3가지 명심하자.</li>
<li>테스트 함수마다 한 개념만 테스트하라</li>
<li>깨끗한 테스트는 F.I.R.S.T 전략을 따른다</li>
<li>테스트 코드를 작성하는 것에만 집중하지말고, 지속적으로 깨끗하게 관리하자</li>
</ul></content:encoded></item><item><title><![CDATA[CleanCode(클린코드) - 7장. 오류 처리]]></title><description><![CDATA[🔖 오늘 읽은 범위 : 7장 - 오류 처리 (day13, 1…]]></description><link>https://sujin-park.github.io/book-club/clean-code-day15/</link><guid isPermaLink="false">https://sujin-park.github.io/book-club/clean-code-day15/</guid><pubDate>Fri, 04 Feb 2022 20:00:00 GMT</pubDate><content:encoded><p>🔖 오늘 읽은 범위 : 7장 - 오류 처리 (day13, 15)</p>
<hr>
<br>
<h2 id="-책에서-기억하고-싶은-내용을-써보세요" style="position:relative;"><a href="#-%EC%B1%85%EC%97%90%EC%84%9C-%EA%B8%B0%EC%96%B5%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%9D%80-%EB%82%B4%EC%9A%A9%EC%9D%84-%EC%8D%A8%EB%B3%B4%EC%84%B8%EC%9A%94" aria-label=" 책에서 기억하고 싶은 내용을 써보세요 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>😃 <strong>책에서 기억하고 싶은 내용을 써보세요.</strong></h2>
<h3 id="오류-코드보다-예외를-사용하라" style="position:relative;"><a href="#%EC%98%A4%EB%A5%98-%EC%BD%94%EB%93%9C%EB%B3%B4%EB%8B%A4-%EC%98%88%EC%99%B8%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%9D%BC" aria-label="오류 코드보다 예외를 사용하라 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><strong>오류 코드보다 예외를 사용하라</strong></h3>
<ul>
<li>오류가 발생하면 예외를 던지는 편이 낫다. 그러면 호출자 코드가 더 깔끔해진다. 논리가 오류 처리 코드와 뒤섞이지 않으니까. (p.131)</li>
</ul>
<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DeviceController</span> <span class="token punctuation">{</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">sendShutDown</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token function">tryToShutDown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">DeviceShutDownError</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
logger<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">tryToShutDown</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">DeviceShutDownError</span> <span class="token punctuation">{</span>
<span class="token function">getHandle</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">private</span> <span class="token class-name">DeviceHandle</span> <span class="token function">getHandle</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">DeviceShutDownError</span><span class="token punctuation">(</span>'invalid <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> '<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre></div>
<h3 id="try-catch-finally-문부터-작성하라" style="position:relative;"><a href="#try-catch-finally-%EB%AC%B8%EB%B6%80%ED%84%B0-%EC%9E%91%EC%84%B1%ED%95%98%EB%9D%BC" aria-label="try catch finally 문부터 작성하라 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><strong>Try-Catch-Finally 문부터 작성하라</strong></h3>
<ul>
<li>예외가 발생할 코드를 짤 때는 try-catch-finally 문으로 시작하는 편이 낫다. 그러면 try 블록에서 무슨 일이 생기든지 호출자가 기대하는 상태를 정의하기 쉬워진다.</li>
</ul>
<h3 id="예외에-의미를-제공하라" style="position:relative;"><a href="#%EC%98%88%EC%99%B8%EC%97%90-%EC%9D%98%EB%AF%B8%EB%A5%BC-%EC%A0%9C%EA%B3%B5%ED%95%98%EB%9D%BC" aria-label="예외에 의미를 제공하라 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><strong>예외에 의미를 제공하라</strong></h3>
<ul>
<li>오류 메시지에 정보를 담아 예외와 함께 던진다. 실패한 연산 이름과 실패 유형도 언급한다. (p.135)</li>
<li>예외를 던질 때는 전후 상황을 충분히 덧붙인다.</li>
</ul>
<h3 id="호출자를-고려해-예외-클래스를-정의하라" style="position:relative;"><a href="#%ED%98%B8%EC%B6%9C%EC%9E%90%EB%A5%BC-%EA%B3%A0%EB%A0%A4%ED%95%B4-%EC%98%88%EC%99%B8-%ED%81%B4%EB%9E%98%EC%8A%A4%EB%A5%BC-%EC%A0%95%EC%9D%98%ED%95%98%EB%9D%BC" aria-label="호출자를 고려해 예외 클래스를 정의하라 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><strong>호출자를 고려해 예외 클래스를 정의하라</strong></h3>
<ul>
<li>애플리케이션에서 오류를 정의할 때 프로그래머에게 가장 중요한 관심사는 오류를 잡아내는 방법이 되어야 한다.</li>
<li>외부 API 를 사용할 때는 감싸기 비법이 최선이다. 외부 API 를 감싸면 외부 라이브러리와 프로그램 사이에서 의존성이 크게 줄어든다.</li>
</ul>
<h3 id="정상-흐름을-정의하라" style="position:relative;"><a href="#%EC%A0%95%EC%83%81-%ED%9D%90%EB%A6%84%EC%9D%84-%EC%A0%95%EC%9D%98%ED%95%98%EB%9D%BC" aria-label="정상 흐름을 정의하라 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><strong>정상 흐름을 정의하라</strong></h3>
<ul>
<li>외부 API 를 감싸 독자적인 예외를 던지고, 코드 위에 처리기를 정의해 중단된 계산을 처리하는 방식이 대개는 멋지지만, 때로는 중단이 적합하지 않은 때도 있다.</li>
</ul>
<p>아래는 비용 청구 애플리케이션에서 총계를 계산하는 허술한 코드다. 예외가 논리를 따라가기 어렵게 만든다. 특수 상황을 처리할 필요가 없다면 코드가 더 간결해질 것이다.</p>
<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token class-name">MealExpenses</span> expenses <span class="token operator">=</span> expenseReportDAO<span class="token punctuation">.</span><span class="token function">getMeals</span><span class="token punctuation">(</span>employee<span class="token punctuation">.</span><span class="token function">getID</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
m_total <span class="token operator">+=</span> expenses<span class="token punctuation">.</span><span class="token function">getTotal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">MealExpensesNotFound</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
m_total <span class="token operator">+=</span> <span class="token function">getMealPerDiem</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">PerDiemExpenses</span> <span class="token keyword">implements</span> <span class="token class-name">MealExpenses</span> <span class="token punctuation">{</span>
<span class="token keyword">public</span> <span class="token keyword">int</span> <span class="token function">getTotal</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 기본값으로 일일 기본 식비를 반환한다.</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token class-name">MealExpenses</span> expenses <span class="token operator">=</span> expenseReportDAO<span class="token punctuation">.</span><span class="token function">getMeals</span><span class="token punctuation">(</span>employee<span class="token punctuation">.</span><span class="token function">getID</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
m_total <span class="token operator">+=</span> expenses<span class="token punctuation">.</span><span class="token function">getTotal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p>ExpenseReportDAO 를 고쳐 위와 같이 청구한 식비가 없다면 일일 기본 식비를 반환하는 MealExpenses 객체를 반환하면 된다. 이를 <code class="language-text">특수 사례 패턴</code> 이라고 부른다. 클래스를 만들거나 객체를 조작해 특수 사례를 처리하는 방식이다.</p>
<h3 id="null-을-반환하지-마라" style="position:relative;"><a href="#null-%EC%9D%84-%EB%B0%98%ED%99%98%ED%95%98%EC%A7%80-%EB%A7%88%EB%9D%BC" aria-label="null 을 반환하지 마라 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><strong>null 을 반환하지 마라</strong></h3>
<ul>
<li>한 줄 건너 하나씩 null 을 확인하는 코드로 가득한 애플리케이션을 지금까지 수도 없이 봤다.</li>
<li>null 을 반환하지 않고 빈 리스트를 반환한다면 코드가 훨씬 깔끔해진다.</li>
</ul>
<h3 id="null-을-전달하지-마라" style="position:relative;"><a href="#null-%EC%9D%84-%EC%A0%84%EB%8B%AC%ED%95%98%EC%A7%80-%EB%A7%88%EB%9D%BC" aria-label="null 을 전달하지 마라 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><strong>null 을 전달하지 마라</strong></h3>
<ul>
<li>메서드에서 null 을 반환하는 방식도 나쁘지만 메서드로 null 을 전달하는 방식은 더 나쁘다.</li>
<li>누군가 null 을 전달하면 실행 오류가 발생한다.</li>
</ul>
<h3 id="결론" style="position:relative;"><a href="#%EA%B2%B0%EB%A1%A0" aria-label="결론 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><strong>결론</strong></h3>
<ul>
<li>깨끗한 코드는 읽기도 좋아야 하지만 안정성도 높아야 한다.</li>
<li>오류 처리를 프로그램 논리와 분리해 독자적인 사안으로 고려하면 튼튼하고 깨끗한 코드를 작성할 수 있다.</li>
<li>오류 처리를 프로그램 논리와 분리하면 독립적인 추론이 가능해지며 코드 유지보수성도 크게 높아진다.</li>
</ul>
<br>
<h2 id="-오늘-읽은-소감은-떠오르는-생각을-가볍게-적어보세요" style="position:relative;"><a href="#-%EC%98%A4%EB%8A%98-%EC%9D%BD%EC%9D%80-%EC%86%8C%EA%B0%90%EC%9D%80-%EB%96%A0%EC%98%A4%EB%A5%B4%EB%8A%94-%EC%83%9D%EA%B0%81%EC%9D%84-%EA%B0%80%EB%B3%8D%EA%B2%8C-%EC%A0%81%EC%96%B4%EB%B3%B4%EC%84%B8%EC%9A%94" aria-label=" 오늘 읽은 소감은 떠오르는 생각을 가볍게 적어보세요 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>🤔 <strong>오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요</strong></h2>
<ul>
<li>오류 코드 또는 if 문으로 작성하는 것보다 예외 처리를 하는 것이 더 좋다는 것을 알고 있음에도 불구하고, 무의식 중에 오류 코드나 if 문을 사용하게 된다. 이번 7장을 읽고 예외 처리를 하는 것을 한번 더 각인시킬 수 있었다.</li>
<li>안정성도 높으면서 깨끗한 코드를 작성할 수 있게 노력해야겠다.</li>
</ul>
<br>
<h2 id="-소감-3줄-요약" style="position:relative;"><a href="#-%EC%86%8C%EA%B0%90-3%EC%A4%84-%EC%9A%94%EC%95%BD" aria-label=" 소감 3줄 요약 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>🔥 <strong>소감 3줄 요약</strong></h2>
<ul>
<li>오류 처리를 프로그램 논리와 분리해 독자적인 사안으로 고려하면 튼튼하고 깨끗한 코드를 작성할 수 있다.</li>
<li>깨끗한 코드는 읽기도 좋아야 하지만 안정성도 높아야 한다. <strong>명심!</strong></li>
<li>Javascript 에는 NullPointerException 이 없고 optional chaining 을 사용하면서 메서드에서 null 이 반환되는 경우를 종종 보았는데, 이런 부분들을 발견하면 리팩토링 해봐야겠다.</li>
</ul></content:encoded></item><item><title><![CDATA[CleanCode(클린코드) - 6장. 객체와 자료 구조]]></title><description><![CDATA[🔖 오늘 읽은 범위 :…]]></description><link>https://sujin-park.github.io/book-club/clean-code-day12/</link><guid isPermaLink="false">https://sujin-park.github.io/book-club/clean-code-day12/</guid><pubDate>Tue, 01 Feb 2022 20:00:00 GMT</pubDate><content:encoded><p>🔖 오늘 읽은 범위 : 6장 - 객체와 자료 구조</p>
<hr>
<br>
<h2 id="-책에서-기억하고-싶은-내용을-써보세요" style="position:relative;"><a href="#-%EC%B1%85%EC%97%90%EC%84%9C-%EA%B8%B0%EC%96%B5%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%9D%80-%EB%82%B4%EC%9A%A9%EC%9D%84-%EC%8D%A8%EB%B3%B4%EC%84%B8%EC%9A%94" aria-label=" 책에서 기억하고 싶은 내용을 써보세요 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>😃 <strong>책에서 기억하고 싶은 내용을 써보세요.</strong></h2>
<h3 id="자료-추상화" style="position:relative;"><a href="#%EC%9E%90%EB%A3%8C-%EC%B6%94%EC%83%81%ED%99%94" aria-label="자료 추상화 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><strong>자료 추상화</strong></h3>
<ul>
<li>자료를 세세하게 공개하기보다는 추상적인 개념으로 표현하는 것이 좋다.</li>
<li>인터페이스나 조회/설정 함수만으로 추상화가 이뤄지지 않는다.</li>
<li>아무 생각 없이 조회/설정 함수를 추가하는 방법이 가장 나쁘다.</li>
</ul>
<h3 id="자료객체-비대칭" style="position:relative;"><a href="#%EC%9E%90%EB%A3%8C%EA%B0%9D%EC%B2%B4-%EB%B9%84%EB%8C%80%EC%B9%AD" aria-label="자료객체 비대칭 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><strong>자료/객체 비대칭</strong></h3>
<ul>
<li>복잡한 시스템을 짜다보면 새로운 함수가 아니라 새로운 자료 타입이 필요한 경우가 생긴다. 이 때는 클래스와 객체 지향 기법이 가장 적합하다. 반면, 새로운 자료 타입이 아니라 새로운 함수가 필요한 경우도 생긴다. 이 때는 절차적인 코드와 자료 구조가 좀 더 적합하다.</li>
</ul>
<h3 id="디미터-법칙" style="position:relative;"><a href="#%EB%94%94%EB%AF%B8%ED%84%B0-%EB%B2%95%EC%B9%99" aria-label="디미터 법칙 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><strong>디미터 법칙</strong></h3>
<ul>
<li>객체는 자료를 숨기고 함수를 공개한다.</li>
<li>
<p>기차 충돌</p>
<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token keyword">final</span> <span class="token class-name">String</span> outputDir <span class="token operator">=</span> ctxt<span class="token punctuation">.</span><span class="token function">getOptions</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getScratchDir</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getAbsolutePath</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<ul>
<li>여러 객체가 한 줄로 이어진 기차처럼 보이는 방식</li>
<li>일반적으로 조잡하다 여겨지는 방식이므로 방식이므로 피하는 편이 좋다. 위 코드는 아래와 같이 나누는 편이 좋다.</li>
</ul>
<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token class-name">Options</span> opts <span class="token operator">=</span> ctxt<span class="token punctuation">.</span><span class="token function">getOptions</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">File</span> scratchDir <span class="token operator">=</span> opts<span class="token punctuation">.</span><span class="token function">getScratchDir</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">final</span> <span class="token class-name">String</span> outputDir <span class="token operator">=</span> scratchDir<span class="token punctuation">.</span><span class="token function">getAbsolutePath</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
</li>
<li>
<p>잡종 구조</p>
<ul>
<li>절반은 객체, 절반은 자료 구조인 잡종 구조가 나온다.</li>
<li>중요한 기능을 수행하는 함수도 있고, 공개 변수나 공개 조회/설정 함수도 있다.</li>
<li>공개 조회/설정 함수는 비공개 변수를 그대로 노출한다.</li>
</ul>
</li>
<li>구조체 감추기</li>
</ul>
<h3 id="자료-전달-객체-dto" style="position:relative;"><a href="#%EC%9E%90%EB%A3%8C-%EC%A0%84%EB%8B%AC-%EA%B0%9D%EC%B2%B4-dto" aria-label="자료 전달 객체 dto permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><strong>자료 전달 객체 (DTO)</strong></h3>
<ul>
<li>자료 구조체의 전형적인 형태는 공개 변수만 있고 함수가 없는 클래스다.</li>
<li>데이터베이스와 통신하거나 소켓에서 받은 메시지의 구문을 분석할 때 유용하다.</li>
<li>데이터베이스에 저장된 가공되지 않은 정보를 애플리케이션 코드에서 사용할 객체로 변환하는 일련의 단계에서 가장 처음으로 사용하는 구조체다.</li>
<li>
<p>활성 레코드</p>
<ul>
<li>DTO 의 특수한 형태다.</li>
<li>공개 변수가 있거나 비공개 변수에 조회/설정 함수가 있는 자료 구조지만, 대개 save 나 find 와 같은 탐색 함수도 제공한다.</li>
</ul>
</li>
</ul>
<h3 id="결론" style="position:relative;"><a href="#%EA%B2%B0%EB%A1%A0" aria-label="결론 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><strong>결론</strong></h3>
<ul>
<li>시스템을 구현할 때, 새로운 자료 타입을 추가하는 유연성이 필요하면 객체가 더 적합하다.</li>
<li>다른 경우로 새로운 동작을 추가하는 유연성이 필요하면 자료 구조와 절차적인 코드가 더 적합하다.</li>
</ul>
<br>
<h2 id="-오늘-읽은-소감은-떠오르는-생각을-가볍게-적어보세요" style="position:relative;"><a href="#-%EC%98%A4%EB%8A%98-%EC%9D%BD%EC%9D%80-%EC%86%8C%EA%B0%90%EC%9D%80-%EB%96%A0%EC%98%A4%EB%A5%B4%EB%8A%94-%EC%83%9D%EA%B0%81%EC%9D%84-%EA%B0%80%EB%B3%8D%EA%B2%8C-%EC%A0%81%EC%96%B4%EB%B3%B4%EC%84%B8%EC%9A%94" aria-label=" 오늘 읽은 소감은 떠오르는 생각을 가볍게 적어보세요 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>🤔 <strong>오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요</strong></h2>
<p>Javascript 를 주로 사용하고 함수형 프로그래밍을 좋아하는데 이번 6장은 객체지향에 집중된 글이어서 가볍게 본 것 같다. 아무래도 함수형 프로그래밍을 좋아한다고 해도 하나에 매몰되지 않고 넓은 인사이트를 가지고 있어야 뭐가 좋고 나쁜건지 구분할 수 있다는 생각을 하고 보니 더 재밌게 본 것 같다. </p>
<br>
<h2 id="-소감-3줄-요약" style="position:relative;"><a href="#-%EC%86%8C%EA%B0%90-3%EC%A4%84-%EC%9A%94%EC%95%BD" aria-label=" 소감 3줄 요약 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>🔥 <strong>소감 3줄 요약</strong></h2>
<ul>
<li>예전에 자료 전달 객체를 사용했을 때는 생각없이 데이터베이스와 통신할 때 사용했었는데 책에서 나와서 반갑기도 하고 다시 공부할 수 있어서 좋았다.</li>
<li>시스템을 구현할 때, 새로운 자료 타입을 추가하는 유연성이 필요하면 객체가 더 적합하다는 것을 명심하자.</li>
<li>객체는 동작을 공개하고 자료를 숨긴다!</li>
</ul></content:encoded></item><item><title><![CDATA[CleanCode(클린코드) - 5장. 형식 맞추기]]></title><description><![CDATA[🔖 오늘 읽은 범위 :…]]></description><link>https://sujin-park.github.io/book-club/clean-code-day10/</link><guid isPermaLink="false">https://sujin-park.github.io/book-club/clean-code-day10/</guid><pubDate>Sun, 30 Jan 2022 20:00:00 GMT</pubDate><content:encoded><p>🔖 오늘 읽은 범위 : 5장</p>
<hr>
<h3 id="-책에서-기억하고-싶은-내용을-써보세요" style="position:relative;"><a href="#-%EC%B1%85%EC%97%90%EC%84%9C-%EA%B8%B0%EC%96%B5%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%9D%80-%EB%82%B4%EC%9A%A9%EC%9D%84-%EC%8D%A8%EB%B3%B4%EC%84%B8%EC%9A%94" aria-label=" 책에서 기억하고 싶은 내용을 써보세요 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>😃 <strong>책에서 기억하고 싶은 내용을 써보세요.</strong></h3>
<br>
<p>주제 : <strong>프로그래머라면 형식을 깔끔하게 맞춰 코드를 짜야 한다.</strong></p>
<br>
<p><strong>형식을 맞추는 목적</strong></p>
<ul>
<li>맨 처음 잡아놓은 구현 스타일과 가독성 수준은 유지보수 용이성과 확장성에 계속 영향을 미친다.</li>
<li>코드 형식은 의사소통의 일환이다. (96p)</li>
</ul>
<p>원활한 소통을 장려하는 코드 형식은 무엇일까?</p>
<br>
<p><strong>적절한 행 길이를 유지하라.</strong></p>
<ul>
<li>500줄을 넘지 않고 대부분 200줄 정도인 파일로도 커다란 시스템을 구축할 수 있다.</li>
<li>반드시 지킬 엄격한 규칙은 아니지만 바람직한 규칙으로 삼으면 좋겠다. 일반적으로 큰 파일보다 작은 파일이 이해하기 쉽다. (97p)</li>
</ul>
<br>
<p><strong>신문 기사처럼 작성하라</strong></p>
<ul>
<li>이름은 간단하면서도 설명이 가능하게 짓는다.</li>
<li>소스 파일 첫 부분은 고차원 개념과 알고리즘을 설명하고, 아래로 내려갈수록 의도를 세세하게 묘사한다.</li>
</ul>
<br>
<p><strong>개념은 빈 행으로 구분하라</strong></p>
<ul>
<li>각 행은 수식이나 절을 나타내고, 일련의 행 묶음은 완결된 생각 하나를 표현한다. 빈 행은 새로운 개념을 시작한다는 시각적 단서다. (98p)</li>
</ul>
<br>
<p><strong>세로 밀집도</strong></p>
<ul>
<li>줄 바꿈이 개념을 분리한다면 세로 밀집도는 연관성을 의미한다. 즉, 서로 밀접한 코드 행은 세로로 가까이 놓여야 한다는 뜻이다.</li>
<li>의미 없는 주석으로 관련 있는 두 인스턴스 변수를 떨어뜨리면 안된다.</li>
</ul>
<p>수직 거리</p>
<ul>
<li>연관성이 깊은 두 개념이 멀리 떨어져 있으면 코드를 읽는 사람이 소스 파일과 클래스를 여기저기 뒤지게 된다.</li>
<li>
<p>변수 선언</p>
<ul>
<li>변수는 사용하는 위치에 최대한 가까이 선언한다.</li>
</ul>
</li>
<li>
<p>인스턴스 변수</p>
<ul>
<li>인스턴스 변수는 클래스 맨 처음에 선언한다.</li>
</ul>
</li>
<li>
<p>종속 함수</p>
<ul>
<li>한 함수가 다른 함수를 호출한다면 두 함수는 세로로 가까이 배치한다.</li>
<li>가능하다면 호출하는 함수를 호출되는 함수보다 먼저 배치한다.</li>
</ul>
</li>
<li>
<p>개념적 유사성</p>
<ul>
<li>개념적인 친화도가 높을수록 코드를 가까이 배치한다. (106p)</li>
</ul>
</li>
</ul>
<br>
<p><strong>세로 순서</strong></p>
<ul>
<li>호출되는 함수를 호출하는 함수보다 나중에 배치한다.</li>
<li>신문 기사와 마찬가지로 가장 중요한 개념을 가장 먼저 표현한다.</li>
<li>세세한 사항은 가장 마지막에 표현한다.</li>
</ul>
<br>
<p><strong>가로 형식 맞추기</strong></p>
<ul>
<li>사실은 80자 이후부터 행 수는 급격하게 감소한다. 프로그래머는 명백하게 짧은 행을 선호한다.</li>
<li>개인적으로는 120자 정도로 행 길이를 제한한다.</li>
</ul>
<br>
<p><strong>가로 공백과 밀집도</strong></p>
<ul>
<li>가로로는 공백을 사용해 밀접한 개념과 느슨한 개념을 표현한다.</li>
<li>
<p>함수를 호출하는 코드에서 괄호 안 인수는 공백으로 분리한다. 쉼표를 강조해 인수가 별개라는 사실을 보여주기 위해서다.</p>
<div class="gatsby-highlight" data-language="tsx"><pre class="language-tsx"><code class="language-tsx">lineWidthHistogram<span class="token punctuation">.</span><span class="token function">addLine</span><span class="token punctuation">(</span>lineSize<span class="token punctuation">,</span> lineCount<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
</li>
</ul>
<br>
<p><strong>들여쓰기</strong></p>
<ul>
<li>들여쓰기한 파일은 구조가 한눈에 들어온다.</li>
<li>
<p>들여쓰기 무시하기</p>
<ul>
<li>때로는 간단한 if 문, while 문, 짧은 함수에서 들여쓰기 규칙을 무시하고픈 유혹이 생긴다.</li>
<li>들여쓰기로 범위를 제대로 표현한 코드를 선호한다.</li>
</ul>
</li>
</ul>
<br>
<h3 id="-오늘-읽은-소감은-떠오르는-생각을-가볍게-적어보세요" style="position:relative;"><a href="#-%EC%98%A4%EB%8A%98-%EC%9D%BD%EC%9D%80-%EC%86%8C%EA%B0%90%EC%9D%80-%EB%96%A0%EC%98%A4%EB%A5%B4%EB%8A%94-%EC%83%9D%EA%B0%81%EC%9D%84-%EA%B0%80%EB%B3%8D%EA%B2%8C-%EC%A0%81%EC%96%B4%EB%B3%B4%EC%84%B8%EC%9A%94" aria-label=" 오늘 읽은 소감은 떠오르는 생각을 가볍게 적어보세요 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>🤔 <strong>오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요</strong></h3>
<ul>
<li>무의식 중에 지키고 있던 형식도 있고, 그렇지 못했던 형식들도 있는 것 같다. 이번에 형식에 대해서 공부를 했으니 좀 더 잘 지켜야겠다.</li>
<li>Prettier, ESLint와 같이 형식을 맞춰주는 툴의 중요성을 느끼게 되었다.</li>
</ul>
<p>🔎 <strong>궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요.</strong></p>
<br>
<h3 id="-소감-3줄-요약" style="position:relative;"><a href="#-%EC%86%8C%EA%B0%90-3%EC%A4%84-%EC%9A%94%EC%95%BD" aria-label=" 소감 3줄 요약 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>🔥 <strong>소감 3줄 요약</strong></h3>
<ul>
<li>프로그래머라면 형식을 깔끔하게 맞춰 코드를 짜야 한다.</li>
<li>신문 기사처럼 작성하라.</li>
<li>Prettier, ESLint 와 같이 형식을 맞춰주는 툴을 보다 적극적으로 활용해야겠다.</li>
</ul></content:encoded></item><item><title><![CDATA[CleanCode(클린코드) - 4장. 주석]]></title><description><![CDATA[🔖 오늘 읽은 범위 : 4장 😃 책에서 기억하고 싶은 내용을 써보세요. 주석은 오래될수록 코드에서 멀어진다. (p.68) 나라면 코드를 깔끔하게 정리하고 표현력을 강화하는 방향으로, 그래서 애초에 주석이 필요 없는 방향으로 에너지를 쏟겠다. (p…]]></description><link>https://sujin-park.github.io/book-club/clean-code-day8/</link><guid isPermaLink="false">https://sujin-park.github.io/book-club/clean-code-day8/</guid><pubDate>Fri, 28 Jan 2022 22:00:00 GMT</pubDate><content:encoded><p>🔖 오늘 읽은 범위 : 4장</p>
<hr>
<p>😃 <strong>책에서 기억하고 싶은 내용을 써보세요.</strong></p>
<ul>
<li>주석은 오래될수록 코드에서 멀어진다. (p.68)</li>
<li>나라면 코드를 깔끔하게 정리하고 표현력을 강화하는 방향으로, 그래서 애초에 주석이 필요 없는 방향으로 에너지를 쏟겠다. (p.69)</li>
<li>주석은 나쁜 코드를 보완하지 못한다. (p.69)</li>
<li>코드로 의도를 표현하라! (p.70)</li>
</ul>
<div class="gatsby-highlight" data-language="jsx"><pre class="language-jsx"><code class="language-jsx"><span class="token comment">// 직원에게 복지 혜택을 받을 자격이 있는지 검사한다.</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>employee<span class="token punctuation">.</span>flags <span class="token operator">&amp;</span> <span class="token constant">HOURLY_FLAG</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>employee<span class="token punctuation">.</span>age <span class="token operator">></span> <span class="token number">65</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
위 코드보다 아래와 같이 주석으로 달려는 서렴ㅇ을 함수로 만들어 표현해도 충분하다<span class="token punctuation">.</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>employee<span class="token punctuation">.</span><span class="token function">isEligibleForFullBenefits</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre></div>
<ul>
<li>
<p>좋은 주석</p>
<ul>
<li>법적인 주석 : 저작권 정보, 소유권 정보</li>
<li>정보를 제공하는 주석</li>
<li>의도를 설명하는 주석</li>
<li>
<p>의미를 명료하게 밝히는 주석</p>
<ul>
<li>때때로 모호한 인수나 반환값은 그 의미를 읽기 좋게 표현하면 이해하기 쉬워진다. 일반적으로는 인수나 반환값 자체를 명확하게 만들면 좋겠지만, 인수나 반환값이 표준 라이브러리나 변경하지 못하는 코드에 속한다면 의미를 명료하게 밝히는 주석이 유용하다.</li>
</ul>
</li>
<li>
<p>결과를 경고하는 주석</p>
<ul>
<li>특정 테스트 케이스를 꺼야 하는 이유를 설명하는 주석이 있다.</li>
</ul>
</li>
<li>
<p>TODO 주석</p>
<ul>
<li>앞으로 할 일을 // TODO 주석으로 남겨두면 편하다.</li>
<li>더 이상 필요 없는 기능을 삭제하라는 알림, 앞으로 발생할 이벤트에 맞춰 코드를 고치라는 주의 등에 유용하다.</li>
<li>주기적으로 TODO 주석을 점검해 없애도 괜찮은 주석은 없애라고 권한다.</li>
</ul>
</li>
<li>중요성을 강조하는 주석</li>
<li>공개 API 에서 Javadocs</li>
</ul>
</li>
<li>
<p>나쁜 주석</p>
<ul>
<li>주절거리는 주석</li>
<li>같은 이야기를 중복하는 주석</li>
<li>오해할 여지가 있는 주석</li>
<li>의무적으로 다는 주석</li>
<li>
<p>이력을 기록하는 주석</p>
<ul>
<li>사람들은 모듈을 편집할 때마다 모듈 첫머리에 주석을 추가한다.</li>
<li>모듈 첫머리 주석은 지금까지 모듈에 가한 변경을 모두 기록하는 일정의 일지 혹은 로그가 된다. (p. 80)</li>
</ul>
</li>
<li>있으나 마나 한 주석</li>
<li>무서운 잡음</li>
<li>함수나 변수로 표현할 수 있다면 주석을 달지 마라</li>
</ul>
<div class="gatsby-highlight" data-language="jsx"><pre class="language-jsx"><code class="language-jsx"><span class="token comment">// 전역 목록 &lt;smodule> 에 속하는 모듈이 우리가 속한 하위 시스템에 의존하는가?</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>smodule<span class="token punctuation">.</span><span class="token function">getDependSubsystems</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span>subSysMod<span class="token punctuation">.</span><span class="token function">getSubSystem</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
이 코드에서 주석을 없애고 다시 표현하면 아래와 같다<span class="token punctuation">.</span>
ArrayList moduleDependees <span class="token operator">=</span> smodule<span class="token punctuation">.</span><span class="token function">getDependSubsystems</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
String ourSubSystem <span class="token operator">=</span> subSysMod<span class="token punctuation">.</span><span class="token function">getSubSystem</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>moduleDependees<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span>ourSubsystem<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre></div>
<ul>
<li>위치를 표시하는 주석</li>
<li>닫는 괄호에 다는 주석</li>
<li>공로를 돌리거나 저자를 표시하는 주석</li>
<li>주석으로 처리한 코드</li>
<li>HTML 주석</li>
<li>
<p>전역 정보</p>
<ul>
<li>주석을 달아야 한다면 근처에 있는 코드만 기술하라. 코드 일부에 주석을 달면서 시스템의 전반적인 정보를 기술하지 마라.</li>
</ul>
</li>
<li>너무 많은 정보</li>
<li>모호한 관계</li>
<li>함수 헤더</li>
<li>
<p>비공개 코드에서 Javadocs</p>
<ul>
<li>공개 API 는 Javadocs 가 유용하지만 공개하지 않을 코드라면 Javadocs 는 쓸모가 없다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<br>
<p>🤔 <strong>오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요</strong></p>
<p>최대한 주석을 작성하지 않으려고 노력하지만, 가끔 내가 잘못 작성한 코드를 보고 이해가 안될 때 주석을 작성하고 싶어진다. 그래도 항상 참고 주석을 작성하지 않고 코드를 변경하려고 노력하는데 이 부분은 잘해왔다고 생각한다.</p>
<p>앞으로 클린 코드에 있는 정보를 기반으로 코드 리뷰 할 때에도 주석이 있으면 주석보다는 코드로 표현해보자고 얘기해봐야겠다.</p>
<br>
<p>🔥 <strong>소감 3줄 요약</strong></p>
<ul>
<li>코드를 깔끔하게 정리하고 표현력을 강화하는 방향으로, 그래서 애초에 주석이 필요 없는 방향으로 에너지를 쏟겠다.</li>
<li>주석은 나쁜 코드를 보완하지 못한다.</li>
<li>좋은 주석은 법적인 주석, 정보, 의도, 결과를 경고하는 주석, TODO 주석이 있다.</li>
</ul></content:encoded></item><item><title><![CDATA[CleanCode(클린코드) - 3장. 함수]]></title><description><![CDATA[🔖 오늘 읽은 범위 : 3장 함수 😃 책에서 기억하고 싶은 내용을 써보세요. 작게 만들어라! 함수를 만드는 첫째 규칙은 작게!다. 함수를 만드는 둘째 규칙은 더 작게!다. (42p…]]></description><link>https://sujin-park.github.io/book-club/clean-code-day6/</link><guid isPermaLink="false">https://sujin-park.github.io/book-club/clean-code-day6/</guid><pubDate>Wed, 26 Jan 2022 22:00:00 GMT</pubDate><content:encoded><p>🔖 오늘 읽은 범위 : 3장 함수</p>
<hr>
<p>😃 <strong>책에서 기억하고 싶은 내용을 써보세요.</strong></p>
<p><strong>작게 만들어라!</strong></p>
<ul>
<li>함수를 만드는 첫째 규칙은 작게!다. 함수를 만드는 둘째 규칙은 더 작게!다. (42p)</li>
<li>각 함수가 너무도 명백했다. 각 함수가 이야기 하나를 표현했다. (43p)</li>
<li>
<p>블록과 들여쓰기</p>
<ul>
<li>If 문/else 문/while 문 등에 들어가는 블록은 한 줄이어야 한다.</li>
<li>대개 거기서 함수를 호출한다. 중첩 구조가 생길만큼 함수가 커져서는 안 된다는 뜻이다.</li>
<li>함수에서 들여쓰기 수준은 1단이나 2단을 넘어서면 안 된다.</li>
</ul>
</li>
</ul>
<p><strong>한가지만 해라!</strong></p>
<ul>
<li>지정된 함수 이름 아래에서 추상화 수준이 하나인 단계만 수행한다면 그 함수는 한 가지 작업만 한다.</li>
<li>단순히 다른 표현이 아니라 의미 있는 이름으로 다른 함수를 추출할 수 있다면 그 함수는 여러 작업을 하는 셈이다. (45p)</li>
<li>
<p>함수 내 섹션</p>
<ul>
<li>한 가지 작업만 하는 함수는 자연스럽게 섹션으로 나누기 어렵다. (45p)</li>
</ul>
</li>
</ul>
<p><strong>함수 당 추상화 수준은 하나로!</strong></p>
<ul>
<li>함수가 한 가지 작업만 하려면 함수 내 모든 문장의 추상화 수준이 동일해야 한다. (45p)</li>
<li>
<p>한 함수 내에 추상화 수준을 섞으면 코드를 읽는 사람이 헷갈린다.</p>
<ul>
<li><code class="language-text">getHtml()</code> 은 추상화 수준이 아주 높다. <code class="language-text">render</code> 는 추상화 수준이 중간이다. <code class="language-text">append(‘\n’)</code>와 같은 코드는 추상화 수준이 아주 낮다.</li>
</ul>
</li>
<li>
<p>위에서 아래로 코드 읽기: 내려가기 규칙</p>
<ul>
<li>위에서 아래로 프로그램을 읽으면 함수 추상화 수준이 한 번에 한 단계씩 낮아진다.</li>
<li>코드는 위에서 아래로 이야기처럼 읽혀야 좋다. (46p)</li>
</ul>
</li>
</ul>
<p><strong>Switch</strong></p>
<ul>
<li>다형적 객체를 생성하는 코드 안에서는 스위치 문을 참는다. 이렇게 상속 관계로 숨긴 후에는 절대로 다른 코드에 노출하지 않는다. (49p)</li>
</ul>
<p><strong>서술적인 이름을 사용하라! (50p)</strong></p>
<ul>
<li>서술적인 이름을 사용하면 개발자 머릿속에서도 설계가 뚜렷해지므로 코드를 개선하기 쉬워진다.</li>
<li>이름을 붙일 때는 일관성이 있어야 한다. 모듈 내에서 함수 이름은 같은 문구, 명사, 동사를 사용한다.</li>
</ul>
<p><strong>함수 인수</strong></p>
<ul>
<li>함수에서 이상적인 인수 개수는 0개이다.</li>
<li>테스트 관점에서 보면 인수는 더 어렵다. 갖가지 인수 조합으로 함수를 검증하는 테스트 케이스를 작성한다고 상상해보라!</li>
<li>SetupTeardownIncluder.render(pageData) 는 이해하기 아주 쉽다. <code class="language-text">pageData</code>객체 내용을 렌더링하겠다는 뜻이다.</li>
<li>
<p>많이 쓰는 단항 형식</p>
<ul>
<li>함수에 인수 1개를 넘기는 이유로 가장 흔한 경우는 두 가지다.</li>
<li>하나는 인수에 질문을 던지는 경우다. <code class="language-text">boolean fileExists(‘MyFile’)</code> 이 좋은 예다. 다른 하나는 인수를 뭔가로 변환해 결과를 변환하는 경우다. InputStream fileOpen(‘MyFile’) 은 String 형의 파일 이름을 InputStream 으로 변환한다.</li>
</ul>
</li>
<li>
<p>플래그 인수</p>
<ul>
<li>함수로 boolean 값을 넘기는 관례는 정말 끔찍하다. 플래그가 참이면 이걸 하고 거짓이면 저걸 한다는 말이니까! (52p)</li>
</ul>
</li>
<li>
<p>이항 함수</p>
<ul>
<li>인수가 2개인 함수는 인수가 1개인 함수보다 이해하기 어렵다.</li>
<li>
<p>Point p = new Point(0, 0) 가 좋은 예다.</p>
<ul>
<li>인수 2개는 한 값을 표현하는 두 요소다. 직교 좌표계 점은 일반적으로 인수 2개를 취한다. (52p)</li>
</ul>
</li>
<li><code class="language-text">assertEquals(expected, actual)</code> 은 당연하게 여겨지는 이항 함수인데, expected 와 actual 의 순서를 인위적으로 기억해야 한다. 여기에도 문제가 있다. (52p)</li>
</ul>
</li>
<li>
<p>삼항 함수</p>
<ul>
<li>인수가 3개인 함수는 인수가 2개인 함수보다 훨씬 더 이해하기 어렵다.</li>
</ul>
</li>
<li>
<p>인수 객체</p>
<ul>
<li>인수가 2-3개 필요하다면 일부를 독자적인 클래스 변수로 선언할 가능성을 짚어본다.</li>
<li>변수를 묶어 넘기려면 이름을 붙여야 하므로 결국은 개념을 표현하게 된다.</li>
</ul>
</li>
<li>
<p>동사와 키워드</p>
<ul>
<li>
<p>단항 함수는 함수와 인수가 동사/명사 쌍을 이뤄야 한다.</p>
<ul>
<li>예시는 write(name) 은 누구나 곧바로 이해한다. 여기를 writeField(name) 으로 하면 이름이 필드라는 사실이 분명히 드러난다. (54p)</li>
</ul>
</li>
<li>
<p>함수 이름에 인수 이름을 넣는다.</p>
<ul>
<li>예시는 assertEquals 보다는 assertExpectedEqualsActual(expected, actual) 로 하면 인수 순서를 기억할 필요가 없다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><strong>부수 효과를 일으키지 마라!</strong></p>
<p>아래는 표준 알고리즘을 사용해 userName 과 password 를 확인한다. 두 인수가 올바르면 true 를 반환하고 아니면 false 를 반환한다. 하지만 함수는 부수 효과를 일으킨다.</p>
<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserValidator</span> <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token class-name">Cryptographer</span> cryptographer<span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">checkPassword</span><span class="token punctuation">(</span><span class="token class-name">String</span> name<span class="token punctuation">,</span> <span class="token class-name">String</span> password<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">User</span> user <span class="token operator">=</span> <span class="token class-name">UserGateway</span><span class="token punctuation">.</span><span class="token function">findByName</span><span class="token punctuation">(</span>userName<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>user <span class="token operator">!=</span> <span class="token class-name">User</span><span class="token punctuation">.</span>NULL<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">String</span> codedPhrase <span class="token operator">=</span> user<span class="token punctuation">.</span><span class="token function">getPhraseEncodedByPassword</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">String</span> phrase <span class="token operator">=</span> cryptographer<span class="token punctuation">.</span><span class="token function">decrypt</span><span class="token punctuation">(</span>codedPhrase<span class="token punctuation">,</span> password<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token string">"Valid Password"</span><span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>phrase<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">Session</span><span class="token punctuation">.</span><span class="token function">initialize</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre></div>
<p>위 코드에서 함수가 일으키는 부수 효과는 Session.initialize() 호출이다. 이름만 봐서는 세션을 초기화한다는 사실이 드러나지 않는다. 그래서 함수 이름만 보고 함수를 호출하는 사용자는 사용자를 인증하면서 기존 세션 정보를 지워버릴 위험에 처한다.</p>
<p>이런 부수 효과가 시간적인 결합을 초래한다. 이런 시간적인 결합이 필요하다면 함수명을 바꾼다. checkPasswordAndInitializeSession 이라는 이름이 훨씬 좋다.</p>
<p><strong>명령과 조회를 분리하라!</strong></p>
<ul>
<li>함수는 뭔가를 수행하거나 뭔가에 답하거나 둘 중 하나만 해야 한다.</li>
<li>
<p>객체 상태를 변경하거나 아니면 객체 정보를 반환하거나 둘 중 하나다.</p>
<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">set</span><span class="token punctuation">(</span><span class="token class-name">String</span> attribute<span class="token punctuation">,</span> <span class="token class-name">String</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">set</span><span class="token punctuation">(</span>'username<span class="token char">', '</span>unclebob'<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span></code></pre></div>
<p>이 함수는 이름이 attribute 인 속성을 찾아 값을 value 로 설정한 후 성공하면 true 를 반환하고 실패하면 false 를 반환한다. 함수를 호출하는 코드만 봐서는 set 이 설정되어 있는지 확인하는 코드인지, 설정하는 코드인지 분간하기 어렵다.</p>
<p>진짜 해결책은 명령과 조회를 분리해 혼란을 애초에 뿌리뽑는 방법이다.</p>
<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">attributeExists</span><span class="token punctuation">(</span>'username'<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">setAttribute</span><span class="token punctuation">(</span>'username<span class="token char">', '</span>unclebob'<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span></code></pre></div>
</li>
</ul>
<p><strong>오류코드보다 예외를 사용하라!</strong></p>
<ul>
<li>명령 함수에서 오류 코드를 반환하는 방식은 명령/조회 분리 규칙을 미묘하게 위반한다.</li>
<li>자칫하면 if 문에서 명령을 표현식으로 사용하기 쉬운 탓이다.</li>
</ul>
<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">deletePage</span><span class="token punctuation">(</span>page<span class="token punctuation">)</span> <span class="token operator">==</span><span class="token operator">=</span> E_OK<span class="token punctuation">)</span></code></pre></div>
<p>위 코드는 동사/형용사 혼란을 일으키지 않는 대신 여러 단계로 중첩되는 코드를 야기한다. 오류 코드를 반환하면 호출자는 오류 코드를 곧바로 처리해야 한다는 문제에 부딪힌다.</p>
<p>오류 코드 대신 예외를 사용하면 오류 처리 코드가 원래 코드에서 분리되므로 코드가 깔끔해진다.</p>
<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token function">deletePage</span><span class="token punctuation">(</span>page<span class="token punctuation">)</span><span class="token punctuation">;</span>
registry<span class="token punctuation">.</span><span class="token function">deleteReference</span><span class="token punctuation">(</span>page<span class="token punctuation">.</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
configKeys<span class="token punctuation">.</span><span class="token function">deleteKey</span><span class="token punctuation">(</span>page<span class="token punctuation">.</span>name<span class="token punctuation">.</span><span class="token function">makeKey</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
logger<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span><span class="token function">getMessage</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<ul>
<li>Try/Catch 블록 뽑아내기</li>
</ul>
<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token function">deletePageAndAllReferences</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">logError</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">deletePageAndAllReferences</span><span class="token punctuation">(</span><span class="token class-name">Page</span> page<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span>
<span class="token function">deletePage</span><span class="token punctuation">(</span>page<span class="token punctuation">)</span><span class="token punctuation">;</span>
registry<span class="token punctuation">.</span><span class="token function">deleteReference</span><span class="token punctuation">(</span>page<span class="token punctuation">.</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
configKeys<span class="token punctuation">.</span><span class="token function">deleteKey</span><span class="token punctuation">(</span>page<span class="token punctuation">.</span>name<span class="token punctuation">.</span><span class="token function">makeKey</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">logError</span><span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
logger<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span><span class="token function">getMessage</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<ul>
<li>
<p>오류 처리도 한 가지 작업이다.</p>
<ul>
<li>오류를 처리하는 함수는 오류만 처리해야 마땅하다. 위 예제처럼</li>
<li>함수에 키워드 try 가 있다면 함수는 try 문으로 시작해 catch/finally 문으로 끝나야 한다는 말이다.</li>
</ul>
</li>
</ul>
<p><strong>반복하지 마라!</strong></p>
<p><strong>구조적 프로그래밍</strong></p>
<ul>
<li>함수는 return 문이 하나여야 한다.</li>
<li>루프 안에서 break 나 continue 를 사용해선 안 되며 goto 는 절대로, 절대로 안된다.</li>
<li>함수를 작게 만든다면 간혹 return, break, continue 를 여러 차례 사용해도 괜찮다.</li>
</ul>
<p><strong>함수를 어떻게 짜죠?</strong></p>
<ul>
<li>함수를 짤 때는 처음에는 길고 복잡하다. 들여쓰기 단계도 많고 중복된 루프도 많다. 코드를 다듬고, 함수를 만들고, 이름을 바꾸고, 중복을 제거한다. 메서드를 줄이고 순서를 바꾼다. 이와중에도 코드는 항상 단위 테스트를 통과한다.</li>
</ul>
<br>
<p>🤔 <strong>오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요</strong></p>
<p>시스템이라는 이야기를 풀어가는데 있다는 사실을 명심하자.</p>
<p>작성하는 함수가 분명하고 정확한 언어로 깔끔하게 같이 맞아떨어져야 이야기를 풀어가기가 쉬워진다는 사실을 기억하자.</p>
<br>
<p>🔥 <strong>소감 3줄 요약</strong></p>
<ul>
<li>함수를 만드는 첫째 규칙은 작게!다. 함수를 만드는 둘째 규칙은 더 작게!다.</li>
<li>함수에서 이상적인 인수 개수는 0개이다.</li>
<li>지정된 함수 이름 아래에서 추상화 수준이 하나인 단계만 수행한다면 그 함수는 한 가지 작업만 한다.</li>
</ul></content:encoded></item><item><title><![CDATA[CleanCode(클린코드) - 2장. 의미 있는 이름]]></title><description><![CDATA[🔖 오늘 읽은 범위 :…]]></description><link>https://sujin-park.github.io/book-club/clean-code-day4/</link><guid isPermaLink="false">https://sujin-park.github.io/book-club/clean-code-day4/</guid><pubDate>Mon, 24 Jan 2022 22:00:00 GMT</pubDate><content:encoded><p>🔖 오늘 읽은 범위 : 2장 ~</p>
<hr>
<p>😃 <strong>책에서 기억하고 싶은 내용을 써보세요.</strong></p>
<ul>
<li>변수(혹은 함수나 클래스)의 존재 이유는? 수행 기능은? 사용 방법은? 따로 주석이 필요하다면 의도를 분명히 드러내지 못했다는 말이다. 의도가 드러나는 이름을 사용하면 코드 이해와 변경이 쉬워진다. (p. 22)</li>
<li>그릇된 단서는 코드 의미를 흐린다. 나름대로 널리 쓰이는 의미가 있는 단어를 다른 의미로 사용해도 안 된다. (p. 24)</li>
<li>변수 이름에 variable 이라는 단어는 단연코 금물이다. 표 이름에 table 이라는 단어도 마찬가지다. ~~ 읽는 사람이 차이를 알도록 이름을 지어라. (p. 27)</li>
<li>발음하기 쉬운 이름은 중요하다. (p. 27)</li>
<li>검색하기 쉬운 이름이 상수보다 좋다. (p. 28)</li>
<li>이제는 멤버 변수에 m_ 이라는 접두어를 붙일 필요도 없다. 사람들은 접두어를 무시하고 이름을 해독하는 방식을 재빨리 익힌다. 코드를 읽을수록 접두어는 관심 밖으로 밀려난다. (p. 30)</li>
<li>인터페이스 이름은 접두어를 붙이지 않는 편이 좋다고 생각한다. 옛날 코드에서 많이 사용하는 접두어 I 는 주의를 흐트리고 과도한 정보를 제공한다. (p. 31)</li>
<li>클래스 이름과 객체 이름은 명사나 명사구가 적합하다. Manger, Processor, Data, Info 등과 같은 단어는 피하고, 동사는 사용하지 않는다. (p. 32)</li>
<li>메서드 이름은 동사나 동사구가 적합하다. (p. 32)</li>
<li>추상적인 개념 하나에 단어 하나를 선택해 이를 고수한다. 똑같은 메서드를 클래스마다 fetch, retrieve, get 으로 제각각 부르면 혼란스럽다. (p. 33)</li>
<li>한 단어를 두 가지 목적으로 사용하지 마라. 다른 개념에 같은 단어를 사용한다면 그것은 말장난에 불과하다. 예를 들어, 지금까지 구현한 add 메서드는 모두가 기존 값 두 개를 더하거나 이어서 새로운 값을 만든다고 가정하자. 새로 작성하는 메서드는 집합에 값 하나를 추가한다. 이 메서드는 insert, append 라는 이름이 적당하다. (p. 34)</li>
<li>프로그래머에게 익숙한 기술 개념은 아주 많다. 기술 개념에는 기술 이름이 가장 적합한 선택이다. (p. 34)</li>
<li>클래스, 함수, 이름 공간에 넣어 맥락을 부여한다. 모든 방법이 실패하면 마지막 수단으로 접두어를 붙인다. (p. 35)</li>
<li>이름에 불필요한 맥락을 추가하지 않도록 주의한다. (p. 37)</li>
<li>우리는 문장이나 문단처럼 읽히는 코드 아니면 적어도 표나 자료 구조처럼 읽히는 코드를 짜는 데만 집중해야 마땅하다. 여느 코드 개선 노력과 마찬가지로 이름 역시 나름대로 바꿨다가는 누군가 질책할지도 모른다. 그렇다고 코드를 개선하려는 노력을 중단해서는 안 된다. (p. 38)</li>
</ul>
<br>
<p>🤔 <strong>오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요</strong></p>
<p>변수, 메서드에 의미 있는 이름을 붙이기는 정말 어렵다. 매번 고민하고 고민해서 붙여도 마음에 들지 않고, 나중에 보면 별로일 때가 많다.</p>
<p>의미 있는 이름을 붙일 수 있게 의식해서 작성을 해야겠다.</p>
<br>
<p>🔥 <strong>소감 3줄 요약</strong></p>
<ul>
<li>의도를 분명히 밝혀라</li>
<li>그릇된 정보를 피하라</li>
<li>의미 있게 구분하라</li>
<li>발음하기 쉬운 이름을 사용하라</li>
<li>검색하기 쉬운 이름을 사용하라</li>
<li>인코딩을 피하라</li>
<li>자신의 기억력을 자랑하지 마라</li>
<li>클래스 이름, 메서드 이름</li>
<li>기발한 이름은 피하라</li>
<li>한 개념에 한 단어를 사용하라</li>
<li>말 장난을 하지 마라</li>
<li>해법 영역에서 가져온 이름을 사용하라</li>
<li>문제 영역에서 가져온 이름을 사용하라</li>
<li>의미 있는 맥락을 추가하라</li>
<li>불필요한 맥락을 없애라</li>
</ul></content:encoded></item><item><title><![CDATA[CleanCode(클린코드) - 1장. 깨끗한 코드]]></title><description><![CDATA[🔖 오늘 읽은 범위 : 1장 ~ 😃 책에서 기억하고 싶은 내용을 써보세요. 깨끗한 코드는 주의 깊게 작성한 코드다. 누군가 시간을 들여 깔끔하고 단정하게 정리한 코드다. (p.1…]]></description><link>https://sujin-park.github.io/book-club/clean-code-day3/</link><guid isPermaLink="false">https://sujin-park.github.io/book-club/clean-code-day3/</guid><pubDate>Sun, 23 Jan 2022 22:00:00 GMT</pubDate><content:encoded><p>🔖 오늘 읽은 범위 : 1장 ~</p>
<hr>
<p>😃 <strong>책에서 기억하고 싶은 내용을 써보세요.</strong></p>
<ul>
<li>깨끗한 코드는 주의 깊게 작성한 코드다. 누군가 시간을 들여 깔끔하고 단정하게 정리한 코드다. (p.12)</li>
<li>중복을 피하라. 한 기능만 수행하라. 제대로 표현하라. 작게 추상화하라. (p.14)</li>
<li>깨끗한 코드는 읽으면서 놀랄 일이 없어야 한다고 워드는 말한다. (p.15)</li>
<li>언어를 단순하게 보이도록 만드는 책임이 우리에게 있다는 뜻이다. (p.15)</li>
<li>예술에 대한 책을 읽는다고 예술가가 된다는 보장은 없다. (p.19)</li>
</ul>
<br>
<p>🤔 <strong>오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요</strong></p>
<p>깨끗한 코드를 작성하기 위해서는 테스트 코드가 필요하다고 되어있지만 프론트는 테스트코드를 작성하기가 모호하다고 생각된다. 컴포넌트 UI 테스팅, 함수에 대한 테스트 코드를 작성하면 프론트엔드는 괜찮은걸까..?</p>
<p>테스트 코드를 작성할 수 있는 함수, 그리고 그 함수를 사용하는 컴포넌트. 이 사고로 개발을 하면 컴포넌트에 UI 에 로직의 결합이 느슨해지지 않을까 생각이 들었다.</p>
<br>
<p>🔥 <strong>소감 3줄 요약</strong></p>
<p>켄트 벡이 제안한 단순한 코드 규칙으로 구현을 시작한다. 중요한 순으로 나열하자면 간단한 코드는</p>
<ul>
<li>모든 테스트를 통과한다.</li>
<li>중복이 없다.</li>
<li>시스템 내 모든 설계 아이디어를 표현한다.</li>
<li>클래스, 메서드, 함수 등을 최대한 줄인다.</li>
</ul>
<p><strong>깨끗한 코드로 언어를 단순하게 보이게 만드는 책임은 나에게 있다.</strong></p></content:encoded></item><item><title><![CDATA[CleanCode(클린코드) - 1장. 깨끗한 코드]]></title><description><![CDATA[🔖 오늘 읽은 범위 : 1장 ~ 😃 책에서 기억하고 싶은 내용을 써보세요. 궁극적으로 코드는 요구사항을 표현하는 언어라는 사실을 명심한다. (p.…]]></description><link>https://sujin-park.github.io/book-club/clean-code-day2/</link><guid isPermaLink="false">https://sujin-park.github.io/book-club/clean-code-day2/</guid><pubDate>Sat, 22 Jan 2022 22:00:00 GMT</pubDate><content:encoded><p>🔖 오늘 읽은 범위 : 1장 ~</p>
<hr>
<p>😃 <strong>책에서 기억하고 싶은 내용을 써보세요.</strong></p>
<ul>
<li>궁극적으로 코드는 요구사항을 표현하는 언어라는 사실을 명심한다. (p.2)</li>
<li>그래도 안 돌아가는 프로그램보다 돌아가는 쓰레기가 좋다고 스스로를 위로한 경험이 있다. 다시 돌아와 나중에 정리하겠다고 다짐했었다. 물론 그때 그 시절 우리는 르블랑의 법칙을 몰랐다. 나중은 결코 오지 않는다. (p.4)</li>
<li>나쁜 코드의 위험을 이해하지 못하는 관리자 말을 그대로 따르는 행동은 전문가답지 못하다. (p.7)</li>
<li>기한을 맞추는 유일한 방법은, 그러니까 빨리 가는 유일한 방법은, 언제나 코드를 최대한 깨끗하게 유지하는 습관이다. (p.7)</li>
<li>깨끗한 코드는 한가지에 집중한다. 각 함수와 클래스와 모듈은 주변 상황에 현혹되거나 오염되지 않은 채 한길만 걷는다. (p.10)</li>
<li>깨끗한 코드는 단순하고 직접적이다. 깨끗한 코드는 잘 쓴 문장처럼 읽힌다. 깨끗한 코드는 결코 설계자의 의도를 숨기지 않는다. 오히려 명쾌한 추상화와 단순한 제어문으로 가득하다. (p.10)</li>
</ul>
<br>
<p>🤔 <strong>오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요</strong></p>
<p>일정에 치여 빠듯하게 개발 할 때는 안 돌아가는 프로그램보다 돌아가는 쓰레기가 낫지라는 위로를 하며 코드 리뷰를 스킵했었다. 그 때는 바쁘니까 코드 리뷰를 스킵하자는 말에 반박을 하지 못했었는데 지금 생각해보면 이 책은 반박할 수 있는 많은 문장들이 열거되어있다.</p>
<br>
<p>🔥 <strong>소감 3줄 요약</strong></p>
<ul>
<li>나쁜 코드의 위험을 이해하지 못하는 관리자 말을 그대로 따르는 행동은 전문가답지 못하다.</li>
<li>깨끗한 코드는 한 가지에 집중한다.</li>
<li>멀리 보면 깨끗한 코드를 유지하는 것이 결국 생산성을 높이는 일이라는 것을 항상 명심하고 개발해야겠다.</li>
</ul></content:encoded></item><item><title><![CDATA[CleanCode(클린코드) - 들어가면서]]></title><description><![CDATA[…]]></description><link>https://sujin-park.github.io/book-club/clean-code-day1/</link><guid isPermaLink="false">https://sujin-park.github.io/book-club/clean-code-day1/</guid><pubDate>Fri, 21 Jan 2022 22:00:00 GMT</pubDate><content:encoded><p>🔖 오늘 읽은 범위 : 추천사 &#x26; 들어가면서</p>
<hr>
<p>😃 <strong>책에서 기억하고 싶은 내용을 써보세요.</strong></p>
<ul>
<li>깨끗한 코드를 작성하는 방법은 배우기 어렵다. 단순히 원칙과 패턴을 안다고 깨끗한 코드가 나오지 않는다. 고생을 해야 한다. 스스로 연습하고 실패도 맛봐야 한다. … 결정을 내리느라 고민하는 모습, 잘못된 결정으로 대가를 치르는 모습도 봐야 한다.</li>
</ul>
<br>
<p>🤔 <strong>오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요</strong></p>
<p>장인 정신을 익히는 과정 2단계</p>
<ul>
<li>장인에게 필요한 원칙, 패턴, 기법, 경험과 같은 지식을 습득해야 한다.</li>
<li>연습과 반복을 통한 체득해야 한다.</li>
</ul>
<br>
<p>🔥 <strong>소감 3줄 요약</strong></p>
<ul>
<li>항상 책을 보면 패턴과 원칙만 단순하게 이해하고 공부가 끝났다고 생각했는데, 이번 클린 코드 책을 보면서 스스로 연습하는 시간을 많이 가져야 할 것 같다.</li>
<li>연습과 반복만이 깨끗한 코드로 가는 길이다.</li>
<li>기분 좋은 책을 본 것처럼 끝나지말고 고통스럽게 열심히 반복하고 체득해야겠다.</li>
</ul></content:encoded></item><item><title><![CDATA[[Git] Git hooks를 이용하여 commit message 에 특정 문자 넣기]]></title><description><![CDATA[Git Hooks 란 Git은 특정 이벤트가 발생했을 때 특정 스크립트를 실행할 수 있도록 Hook 이라는 기능을 지원한다. 프로젝트에 커밋을 하거나 푸시하기 전에 린트 또는 테스트를 실행할 수 있고, commit message…]]></description><link>https://sujin-park.github.io/web/git-prepare-commit-msg/</link><guid isPermaLink="false">https://sujin-park.github.io/web/git-prepare-commit-msg/</guid><pubDate>Sun, 19 Dec 2021 11:50:00 GMT</pubDate><content:encoded><h2 id="git-hooks-란" style="position:relative;"><a href="#git-hooks-%EB%9E%80" aria-label="git hooks 란 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Git Hooks 란</h2>
<p>Git은 특정 이벤트가 발생했을 때 특정 스크립트를 실행할 수 있도록 Hook 이라는 기능을 지원한다. 프로젝트에 커밋을 하거나 푸시하기 전에 린트 또는 테스트를 실행할 수 있고, commit message 작성에 도움을 주는 hook 또한 있다. </p>
<br>
<p>Hooks 는 기본적으로 프로젝트의 <code class="language-text">.git/hooks</code> 에 위치한다. </p>
<img width="658" alt="스크린샷 2021-12-05 오후 8 55 39" src="https://user-images.githubusercontent.com/29244798/146679364-308e4534-9dfd-4850-b9f0-59740e8dd0ec.png">
<br>
<p>위 예제는 shell script 와 Perl script 로 작성되어 있지만, 실행할 수 있다면 Ruby 또는 Python 과 같이 익숙한 언어로 작성할 수도 있다. 위 예제에서 <code class="language-text">.sample</code> 확장자만 제거하여도 바로 hook을 사용할 수 있다.</p>
<br>
<p>sample 파일은 그대로 유지하고 새로 생성하고 싶다면 아래와 같이 touch 명령어를 이용하여 파일을 생성할 수 있다. 생성만 하면 되는 것은 아니고 <code class="language-text">실행할 수 있는 권한</code>을 줘야 한다. </p>
<div class="gatsby-highlight" data-language="bash"><pre class="language-bash"><code class="language-bash">$ <span class="token function">vi</span> GIT_REPOSITORY/.git/hooks/pre-commit
$ <span class="token function">chmod</span> +x GIT_REPOSITORY/.git/hooks/prepare-commit-msg</code></pre></div>
<br>
<h2 id="hooks-종류" style="position:relative;"><a href="#hooks-%EC%A2%85%EB%A5%98" aria-label="hooks 종류 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Hooks 종류</h2>
<h3 id="pre-commit" style="position:relative;"><a href="#pre-commit" aria-label="pre commit permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>pre-commit</h3>
<p>커밋할 때 가장 먼저 호출되는 Hook 으로 커밋 메시지를 작성하기 전에 호출된다. pre-commit hook 에서는 린트를 실행하여 코드 스타일을 검사하거나, 라인 끝의 공백 문자를 검사하거나 테스트를 한다.</p>
<p>아래 명령어를 실행하면 commit 시 pre-commit hook 을 <code class="language-text">생략</code>할 수 있다.</p>
<div class="gatsby-highlight" data-language="bash"><pre class="language-bash"><code class="language-bash">$ <span class="token function">git</span> commit --no-verify</code></pre></div>
<h3 id="prepare-commit-msg" style="position:relative;"><a href="#prepare-commit-msg" aria-label="prepare commit msg permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>prepare-commit-msg</h3>
<p>커밋 메시지를 수정하기 전에 먼저 prefix 또는 suffix 를 붙이는 것과 같이 hook 을 통해 커밋 메시지를 손보고 싶을 때 사용한다.</p>
<h3 id="commit-msg" style="position:relative;"><a href="#commit-msg" aria-label="commit msg permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>commit-msg</h3>
<p>이 hook 은 커밋 메시지가 들어 있는 임시 파일의 경로를 argument 로 받고 스크립트가 0이 아닌 값을 반환하면 커밋이 되지 않는다. 이 hook에서는 최종적으로 커밋이 완료되기 전에 프로젝트 상태나 커밋 메시지를 검증한다.</p>
<h3 id="post-commit" style="position:relative;"><a href="#post-commit" aria-label="post commit permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>post-commit</h3>
<p>커밋이 완료되면 post-commit hook이 실행되므로 post-commit 은 커밋한 것을 동료나 다른 프로그램에 노티를 줄 때 사용할 수 있다.</p>
<h3 id="pre-rebase" style="position:relative;"><a href="#pre-rebase" aria-label="pre rebase permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>pre-rebase</h3>
<p>rebase 하기 전에 실행되는 훅으로 이미 push 한 커밋을 rebase 하지 못하게 할 수 있는 hook 으로 사용한다. Git 이 기본적으로 제공해주는 pre-rebase.sample 코드에 예제 또한 있다.</p>
<h3 id="post-rewrite" style="position:relative;"><a href="#post-rewrite" aria-label="post rewrite permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>post-rewrite</h3>
<p>커밋을 변경하는 명령을 실행했을 때 실행되는 훅으로 용량이 크거나 Git 이 관리하지 않는 파일을 옮길 때, 문서를 자동으로 생성할 때 사용한다.</p>
<h3 id="post-merge" style="position:relative;"><a href="#post-merge" aria-label="post merge permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>post-merge</h3>
<p>Merge 가 끝나고 나서 실행되는 hook이다.</p>
<br>
<h2 id="hooks-사용-예제" style="position:relative;"><a href="#hooks-%EC%82%AC%EC%9A%A9-%EC%98%88%EC%A0%9C" aria-label="hooks 사용 예제 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Hooks 사용 예제</h2>
<p>동료와 협업할 때 기본적으로 Git commit message 에 대해 포맷을 논의하고 동일하게 작성하려고 노력을 한다. 이 노력을 각자 할 수도 있겠지만, 이번에는 Git hooks 중 prepare-commit-msg 를 사용하여 Git 이 어느정도 자동으로 해줄 수 있는 방법을 소개해보려고 한다.</p>
<br>
<p><strong>가이드</strong></p>
<ul>
<li>하나의 저장소 내에 여러 개의 프로젝트가 존재하여 프로젝트의 이름을 prefix 로 작성</li>
<li>feature, refactoring, fix 등 해당 커밋의 목적이 무엇인지 작성</li>
<li>마지막으로 작성된 커밋 메시지</li>
</ul>
<p>위 요구사항에 부합하는 prepare-commit-msg 를 아래와 같이 작성해보았다.</p>
<div class="gatsby-highlight" data-language="tsx"><pre class="language-tsx"><code class="language-tsx"><span class="token constant">COMMIT_MSG_FILE</span><span class="token operator">=</span>$1
<span class="token constant">BRANCH_NAME</span><span class="token operator">=</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">git rev-parse --abbrev-ref HEAD</span><span class="token template-punctuation string">`</span></span>
<span class="token constant">PROJECT_NAME</span><span class="token operator">=</span><span class="token string">''</span>
<span class="token constant">PREFIX</span><span class="token operator">=</span><span class="token string">''</span>
<span class="token keyword">if</span> <span class="token punctuation">[</span><span class="token punctuation">[</span> <span class="token string">"${BRANCH_NAME}"</span> <span class="token operator">==</span> <span class="token operator">*</span><span class="token string">"/"</span><span class="token operator">*</span> <span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">;</span>then
<span class="token constant">PROJECT_NAME</span><span class="token operator">=</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">echo </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">BRANCH_NAME</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> | cut -d '/' -f1</span><span class="token template-punctuation string">`</span></span>
<span class="token constant">PREFIX</span><span class="token operator">=</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">echo </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">BRANCH_NAME</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> | cut -d '/' -f2 | cut -d '-' -f1</span><span class="token template-punctuation string">`</span></span>
fi
<span class="token constant">FIRST_LINE</span><span class="token operator">=</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">head -n1 </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">COMMIT_MSG_FILE</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span>
<span class="token keyword">if</span> <span class="token punctuation">[</span><span class="token punctuation">[</span> $<span class="token punctuation">{</span><span class="token constant">PROJECT_NAME</span><span class="token punctuation">}</span> <span class="token operator">==</span> <span class="token string">''</span> <span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">;</span> then
exit
fi
<span class="token keyword">if</span> <span class="token punctuation">[</span> <span class="token operator">-</span>z <span class="token string">"$FIRST_LINE"</span> <span class="token punctuation">]</span><span class="token punctuation">;</span> then
sed <span class="token operator">-</span>i <span class="token string">".bak"</span> <span class="token string">"1s/^/[$PROJECT_NAME] $PREFIX /"</span> $<span class="token punctuation">{</span><span class="token constant">COMMIT_MSG_FILE</span><span class="token punctuation">}</span>
fi</code></pre></div>
<p>가이드에 부합하지 않는 브랜치를 복잡한 정규식을 활용하여 예외케이스를 작성해주면 좋을 것 같았지만 우선 1차적으로 구현을 위해 위와 같이 작성하였다.</p>
<p>그럼 이제 실제로 커밋을 생성한다고 가정해보려고 한다.</p>
<p>아래는 위 가이드를 만족하는 테스트 브랜치명이다. 브랜치명을 <code class="language-text">project-name/feature-XXX</code> 라고 생성하고 </p>
<p><code class="language-text">git commit</code> 명령어를 실행하면 아래와 같이 [project] feature 라는 접두사가 붙는다.</p>
<img width="582" alt="스크린샷 2021-12-19 오후 11 39 39" src="https://user-images.githubusercontent.com/29244798/146679378-38f64534-f0a0-4794-9244-a67eb8615551.png">
<br>
가이드를 만족하지 않는 브랜치명을 작성하게 되면 아래와 같이 공백인 것을 볼 수 있다.
<img width="579" alt="스크린샷 2021-12-19 오후 11 40 01" src="https://user-images.githubusercontent.com/29244798/146679398-b61a3b5a-404d-4f7d-800a-8207815354d1.png">
<br>
<br>
<br>
<p><strong>참고</strong></p>
<p><a href="https://mincong.io/2019/07/23/prepare-commit-message-using-git-hook/">https://mincong.io/2019/07/23/prepare-commit-message-using-git-hook/</a></p>
<p><a href="https://ohgyun.com/639">https://ohgyun.com/639</a></p>
<p><a href="https://techblog.woowahan.com/2530/">https://techblog.woowahan.com/2530/</a></p>
<p><a href="https://git-scm.com/docs/githooks">https://git-scm.com/docs/githooks</a></p></content:encoded></item><item><title><![CDATA[[Git] Git tag, Release Drafter로 release note 작성하기]]></title><description><![CDATA[Git tag Git에서 란 특정 커밋을 태깅하는 것으로 특정 커밋을 가리키는 링크라고 할 수 있다. 커밋은 checkout 하여 작업 내용에 대해 수정할 수 있지만, tag는 수정이 불가능하다. tag…]]></description><link>https://sujin-park.github.io/web/git-tag-release-drafter/</link><guid isPermaLink="false">https://sujin-park.github.io/web/git-tag-release-drafter/</guid><pubDate>Sat, 04 Sep 2021 16:32:00 GMT</pubDate><content:encoded><h2 id="git-tag" style="position:relative;"><a href="#git-tag" aria-label="git tag permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Git tag</h2>
<p>Git에서 <code class="language-text">tag</code>란 특정 커밋을 태깅하는 것으로 특정 커밋을 가리키는 링크라고 할 수 있다. 커밋은 checkout 하여 작업 내용에 대해 수정할 수 있지만, tag는 수정이 불가능하다. <strong>tag는 보통 소프트웨어의 버전을 명시하거나 릴리즈 할 때 사용한다.</strong></p>
<h3 id="tag-조회" style="position:relative;"><a href="#tag-%EC%A1%B0%ED%9A%8C" aria-label="tag 조회 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>tag 조회</h3>
<div class="gatsby-highlight" data-language="bash"><pre class="language-bash"><code class="language-bash"><span class="token comment"># 이미 존재하는 모든 tag 조회</span>
$ <span class="token function">git</span> tag
v1.1.0
v1.2.0
v1.3.0
v1.4.0
v1.5.0
<span class="token comment"># 이미 존재하는 tag 중 검색패턴을 사용하여 조회</span>