-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreport.tex
1306 lines (1104 loc) · 84.1 KB
/
report.tex
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
\documentclass[12pt]{report}
\usepackage{graphicx}
\usepackage[utf8]{vietnam}
\usepackage[left=3cm, right=3cm, top=3cm, bottom =3cm]{geometry}
\usepackage{pdfpages}
\usepackage{fancyhdr}
\usepackage{hyperref}
\usepackage{etoolbox}
% \setcounter{tocdepth}{4}
% Link color setup
\hypersetup{
colorlinks = true,
linkcolor = black,
citecolor = blue
}
% Change format of page
\pagestyle{fancy}
\fancyhf{}
\fancyhead{}
\fancyfoot{}
\fancyhead[L]{Kỹ thuật lập trình}
\fancyfoot[L]{Nhóm 6 - KSTN-CNTT-K60}
\fancyfoot[R]{\thepage}
\renewcommand{\headrulewidth}{1pt}
\renewcommand{\footrulewidth}{1pt}
\patchcmd{\chapter}{\thispagestyle{plain}}{\thispagestyle{fancy}}{}{}
\renewcommand{\thesection}{\Roman{section}}
\renewcommand{\thesubsection}{\thesection.\arabic{subsection}}
% format
\usepackage{titlesec}
\usepackage{etoolbox}
\makeatletter
\patchcmd{\ttlh@hang}{\parindent\z@}{\parindent\z@\leavevmode}{}{}
\patchcmd{\ttlh@hang}{\noindent}{}{}{}
\makeatother
\titleformat{\subsection}
{\normalfont\large\bfseries}{\thesubsection}{1em}{}
\titleformat{\subsubsection}
{\normalfont\normalsize\sffamily\bfseries}{\thesubsubsection}{1em}{}
% PYTHON
% Default fixed font does not support bold face
\DeclareFixedFont{\ttb}{T1}{txtt}{bx}{n}{12} % for bold
\DeclareFixedFont{\ttm}{T1}{txtt}{m}{n}{12} % for normal
% Custom colors
\usepackage{color}
\definecolor{deepblue}{rgb}{0,0,0.5}
\definecolor{deepred}{rgb}{0.6,0,0}
\definecolor{deepgreen}{rgb}{0,0.5,0}
\usepackage{listings}
% Python style for highlighting
\newcommand\pythonstyle{\lstset{
language=Python,
basicstyle=\sffamily\ttm,
otherkeywords={self}, % Add keywords here
keywordstyle=\sffamily\bfseries\ttb\color{deepblue},
emph={MyClass,__init__}, % Custom highlighting
emphstyle=\sffamily\ttb\color{deepred}, % Custom highlighting style
stringstyle=\sffamily\color{deepgreen},
frame=tb, % Any extra options here
showstringspaces=false , %
tabsize = 4
}}
% Python environment
\lstnewenvironment{python}[1][]
{
\pythonstyle
\lstset{#1}
}
{}
% Python for external files
\newcommand\pythonexternal[2][]{{
\pythonstyle
\lstinputlisting[#1]{#2}}}
% Python for inline
\newcommand\pythoninline[1]{{\pythonstyle\lstinline!#1!}}
% END PYTHON
\patchcmd{\abstract}{LỜI NÓI ĐẦU}{Summary}{}{}
\begin{document}
\includepdf{title.pdf}
\newpage
\setcounter{page}{1}
\begin{center}
\LARGE\bfseries LỜI NÓI ĐẦU
\end{center}
Lập trình là một công việc ngày càng trở nên phổ biến và quan trọng đối với những người làm việc trong lĩnh vực công nghệ nói chung. Việc viết được một chương trình để mô phỏng lại một số thao tác hữu hạn các bước mà máy tính phải làm, chẳng qua là việc sử dụng ngôn ngữ lập trình để tạo nên một dãy các câu lệnh yêu cầu các thao tác tương ứng của máy tính để đáp ứng được mục đích đề ra ban đầu của người lập trình không phải là một công việc quá khó. Cũng như việc giao tiếp hằng ngày giữa con người với nhau, chúng ta chỉ cần biết cách dùng từ, biết một chút ngữ pháp, là có thể giúp được đối phương hiểu được điều ta muốn truyền đạt. Tuy nhiên, giao tiếp thì có Nghệ Thuật Giao Tiếp, và cũng thế, lập trình phải có Kỹ Thuật Lập Trình. Nếu giao tiếp tốt là một yếu tố quyết định thành công của nhiều người, thì Kỹ Thuật Lập Trình cũng là một trong những yếu tố đánh giá được trình độ của người lập trình viên. Lập trình cũng có nghệ thuật, kỹ thuật cũng có nét đẹp riêng của nó.
Ngôn ngữ lập trình hiện nay rất đa dạng, rất nhiều những ngôn ngữ với những thế mạnh riêng được sử dụng. Tuy nhiên chung quy lại, công việc lập trình vẫn luôn tuân theo những quy tắc nhất định. Và luôn tồn tại những chuẩn mực chung trong việc sử dụng và bố trí những câu lệnh sao cho chương trình của chúng ta ngắn gọn, dễ hiểu, dễ phân tích, dễ tìm kiếm, dễ phát triển,... Nắm được những chuẩn mực đó, sẽ không còn là vấn đề trong việc cố gắng biến những ý tưởng, thuật toán thành những chương trình cho dù bạn được yêu cầu phải sử dụng ngôn ngữ gì đi chăng nữa!
Từ yêu cầu thực tiễn đó, nhóm chúng em xin tổng hợp lại một số nguyên tắc, cũng như kinh nghiệm của các chuyên gia nổi tiếng thể giới về công nghệ thông tin. Tài liệu sử dụng gồm có Steve McConnell. Code Complete, Second Edition ; Publisher: Microsoft Press; Pub Date: une 09, 2004; Print ISBN: 0-7356-1967-0; Pages: 960. Và bài giảng Introduction to Computer Science and Programming in Python tại https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-0001 \\
-introduction-to-computer-science-and-programming-in-python-fall2016/index.htm của trường đại học MIT. Cùng với sự kết hợp ăn ý và phân chia công việc hợp lý, cả nhóm đã hoàn thành bản báo cáo với tất cả tâm huyết và đam mê nghiên cứu. Xin được gửi lời cảm ơn chân thành đến Thầy Huỳnh Quyết Thắng, giảng viên khoa Công nghệ phần mềm. Trường Đại học Bách Khoa Hà Nội – đã hết lòng giúp đỡ, hướng dẫn, chỉ dạy tận tình để nhóm em có thể hoàn thành được đề tài này.
Vì đây là một trong những bản báo cáo đầu tiên mà nhóm thực hiện nên không thể tránh khỏi sai sót, rất mong được nhận mọi ý kiên góp ý từ thầy cô và các bạn.
Xin chân thành cảm ơn!
\newpage
\tableofcontents
\newpage
\section{\bfseries Tổng hợp kỹ thuật viết mã nguồn với các cấu trúc lập trình}
\subsection{Sử dụng chương 14 – Tổ chức các câu lệnh tuần tự.}
\noindent Các kỹ thuật tiêu biểu gồm:
\subsubsection{KT 14.1. The strongest principle for organizing straight-line code is ordering dependencies.}
Nguyên tắc mạnh nhất trong tổ chức câu lệnh tuần tự là phụ thuộc tuần tự.
\begin{itemize}
\item Những câu lệnh có quan hệ trực tiếp lẫn nhau được nhóm vào thành một khối.
\item Viết code để đọc từ trên xuống .
\item Sự phụ thuộc giữa các dòng lệnh phải được tổ chức rõ ràng.
\end{itemize}
Ví dụ trong insertion sort:
\begin{python}
def insertion_sort(a, n):
for i in range(0, n):
for j in range(i, n):
if a[i] > a[j]:
x = a[i]
a[i] = a[j]
a[j] = x
print("\nDay sau khi sap xep: ")
print(a)
sophantu = input("\nNhap so phan tu: ")
sophantu = int(sophantu)
b = []
for i in range(0, sophantu):
alpha = int(input("a[" + str(i) + "] = "))
b.append(alpha)
insertion_sort(b, sophantu)
\end{python}
\subsubsection{KT 14.2. Dependencies should be made obvious through the use of good routine names, parameter lists, comments, and—if the code is critical enough—housekeeping variables.}
Sự phụ thuộc giữa các câu lệnh nên được thể hiện rõ qua việc đặt tên thủ tục, danh sách tham số, chú thích, và có đủ các biến housekeeping để kiểm tra thứ tự phụ thuộc của các thành phần critical của mã.
\begin{itemize}
\item Đặt tên chương trình để câu lệnh là rõ ràng.
\item Tổ chức code để câu lệnh rõ ràng.
\item Sử dụng thông số để câu lệnh rõ ràng.
\end{itemize}
Ví dụ trong Check Prime Number:
\begin{python}
import math
def CheckPrime(a):
if a < 2: return 0
elif a == 2: return 1
elif a == 3: return 1
else:
for i in range(2, int(math.sqrt(a) + 1)):
if a % i == 0: return 0
else: return 1
a = int(input('a = '))
if CheckPrime(a) == 1:
print('a la so nguyen to')
else:
print('a khong la so nguyent to')
\end{python}
\subsubsection{KT 14.3. If code doesn't have order dependencies, keep related statements as close together as possible.}
Nếu đoạn mã không có phụ thuộc theo thứ tự, các câu lệnh có liên quan với nhau nên được đặt gần nhau nhất có thể.
\begin{itemize}
\item Tạo code để đọc từ trên xuống dưới. Tránh rẽ nhánh và vòng vo.
\item Gom những biến liên quan lại và cố gắng đặt chúng gần nhau.
\item Giảm thiểu thời gian sống của biến, đồng thời rút ngắn tối đa khoảng cách giữa các tham chiếu trên cùng một đối tượng. Điều này làm giảm cơ hội của lỗi khởi tạo, tăng khả năng phát hiện các đối tượng cần tìm kiếm.
\item Gom những ý liên quan một cách logic. Nếu câu lệnh liên quan về dữ liệu hay mục đích, giữ chúng gần nhau nhất có thể.
\end{itemize}
Ví dụ trong phần CheckPrime:
\begin{python}
def CheckPrime(a):
if a < 2: return 0
elif a == 2: return 1
elif a == 3: return 1
else:
for i in range(2, int(math.sqrt(a) + 1)):
if a % i == 0: return 0
else: return 1
\end{python}
\subsection{Sử dụng chương 15 – Sử dụng câu lệnh If-Then}
\noindent Các kỹ thuật tiêu biểu gồm:
\subsubsection{KT 15.1. For simple if-else statements, pay attention to the order of the if and else clauses, especially if they process a lot of errors. Make sure the nominal case is clear.}
Đối với câu đơn if-else, chú ý đến thứ tự của if và else , đặc biệt là nếu chúng xử lý rất nhiều lỗi. Hãy chắc chắn rằng các trường hợp danh nghĩa là rõ ràng.
\begin{itemize}
\item Vạch ra đường thực hiện thông thường trước rồi mới đặt câu lệnh điều kiện cho trường hợp bất thường. điều này cần thiết cho việc dễ đọc mã nguồn cũng như thực thi.
\item Với các câu điều kiện so sánh >, >=, <, <=, hãy đảm bảo khi điều kiện = xảy ra thì rẽ nhánh hợp lí.
\item Đưa trường hợp ta mong chờ sẽ thực hiện (trường hợp bình thường) sau câu lệnh if hơn là else. Điều này đảm bảo khi ta xem lại code, có thể tìm kiếm nhanh chóng hơn, máy tính thực hiện cũng có thể nhanh hơn trong nhiều trường hợp do không cần xét quá nhiều trường hợp hãn hữu.
\item Tránh sử dụng câu lệnh if rỗng (null if). Nếu sử dụng, hãy chú thích để người đọc dễ hiểu hơn.
\item Hãy xem xét các mệnh đề else Nếu bạn nghĩ rằng bạn cần một câu lệnh đơn giản if, hãy cân nhắc xem bạn có cần sử dụng mệnh để else không?
\item Kiểm tra lại tính đúng đắn của các mệnh đề, điều này là rõ ràng cần thiết.
\item Kiểm tra sự đảo ngược của lệnh if và else. Rất có thể mệnh đề if và else của bạn bị đảo ngược cho nhau.
\end{itemize}
Ví dụ thuật toán Bubble Sort:
\begin{python}
#giai phuong trinh bac hai:
import math
def solve_equation(a, b, c):
if a == 0:
print('day khong phai phuong trinh bac hai')
else:
delta = b*b - 4*a*c
if delta < 0:
print('phuong trinh vo nghiem thuc')
elif delta == 0:
x = float(-float(b) / (2*a))
print('phuong trinh co nghiem kep x = ')
print(x)
else:
x1 = float((-b+math.sqrt(delta))/(2*a))
x2 = float((-b-math.sqrt(delta))/(2*a))
print('phuong trinh co hai nghiem phan biet x1 = '
str(x1) + 'x2 = ' + str(x2))
\end{python}
\subsubsection{KT 15.2. For if-then-else chains and case statements, choose an order that maximizes read-ability.}
Đối với chuỗi các mệnh đề if-then-else và câu lệnh case, chọn một thứ tự có thể tối đa hóa khả năng đọc.
\begin{itemize}
\item Sử dụng các hàm thay vì dùng kết hợp các câu lệnh and, or.
\item Đưa trường hợp mong chờ sẽ được thực hiện nhất lên đầu tiên.
\item Hãy đảm bảo tất cả các trường hợp đều đã được xem xét.
\item Nếu ngôn ngữ không hỗ trợ chuỗi lệnh if-then-else thì sử dụng các câu lệnh case và ngược lại.
\end{itemize}
\begin{python}
#giai phuong trinh bac hai:
import math
def solve_equation(a, b, c):
if a != 0:
delta = b*b - 4*a*c
if delta > 0:
x1 = float((-b + math.sqrt(delta))/(2*a))
x2 = float((-b - math.sqrt(delta))/(2*a))
print('phuong trinh co hai nghiem phan biet x1 = '
+ str(x1) + 'x2 = ' + str(x2))
elif delta == 0:
x = float(-b/(2*a))
print('phuong trinh co nghiem kep x =')
print(x)
else:
print('phuong trinh vo nghiem thuc')
else:
print('day khong phai phuong trinh bac hai')
\end{python}
\subsubsection{KT 15.3. To trap errors, use the default clause in a case statement or the last else in a chain of if-then-else statements.}
Để bẫy lỗi, sử dụng default khi sử dụng lệnh case hoặc else khi sử dụng chuỗi lệnh if – then – else.
\vspace*{3mm}
Lưạ chọn thứ tự các trường hợp để có hiệu quả nhất:
\begin{itemize}
\item Thứ tự các trường hợp theo bảng chữ cái hoặc số lượng.
\item Đặt các trường hợp thong thường lên đầu.
\item Sắp xếp các trường hợp theo xác suất.
\end{itemize}
Ví dụ trong đoạn code sau:
\begin{python}
s = input('Chon mot trong nhung phuong an A,B,C')
if (s == 'A'):
dothecaseA()
elif (s == 'B'):
dothecaseB()
elif (s == 'C'):
dothecaseC()
else:
print('Ban da nhap sai, ban phai chon mot trong nhung' +
' phuong an A,B,C')
\end{python}
\subsubsection{KT 15.4. All control constructs are not created equal. Choose the control construct that's most appropriate for each section of code.}
Tất cả các cấu trúc điều khiển không được tạo ra như nhau. Chọn cấu trúc điều khiển mà là thích hợp nhất cho mỗi phần của mã.
\begin{itemize}
\item Chỉ sử dụng switch – case cho những trường hợp biến case đơn giản (char, số).
\item Sử dụng default, else để xử lý các trường hợp không mong muốn.
\item Python không hỗ trợ lệnh switch-case, cho nên ta buộc phải sử dụng cấu trúc điều khiển if-then-else.
\end{itemize}
\subsection{Sử dụng chương 16 – Vòng lặp}
\noindent Các kỹ thuật tiêu biểu gồm:
\subsubsection{KT 16.1. Loops are complicated. Keeping them simple helps readers of your code.}
Vòng lặp thì phức tạp. Giữ cho vòng lặp trở nên đơn giản hơn cho người đọc dễ đọc code của bạn hơn.
\vspace*{3mm}
Lựa chọn loại vòng lặp:
\begin{itemize}
\item Sử dụng biến đếm giúp xác định số lần lặp cụ thể.
\item Đánh giá một vòng lặp ở thời gian mà vòng lặp sẽ thực hiện, nó sẽ kết thúc sau bao nhiêu vòng lặp hay lặp vô hạn.
\item Các loại vòng lặp khác nhau thì khác biệt ở vị trí câu lệnh kiểm tra điều kiện kết thúc (vị trí này có thể ở đầu, giữa hoặc ở cuối vòng lặp).
\item Các loại vòng lặp cũng được phân biệt bằng độ linh hoạt của chúng -> là việc các vòng lặp sẽ chạy trong một số lần nhất định hay phải kiểm tra sự kết thúc sau mỗi chu kì.
\item Sử dụng linh hoạt vòng lặp while và for.
\end{itemize}
Vòng lặp while:
\begin{python}
count = 0
while (count < 9):
print('So thu tu cua ban la: ', count)
count += 1
\end{python}
Vòng lặp for:
\begin{python}
for letter in 'Python':
print 'Chu cai hien tai: ', letter
qua = ['chuoi', 'tao', 'xoai']
for q in qua:
print "Ban co thich an: ", q
\end{python}
\subsubsection{KT16.2. Techniques for keeping loops simple include avoiding exotic kinds of loops, minimizing nesting, making entries and exits clear, and keeping housekeeping code in one place.}
Kĩ thuật để làm cho vòng lặp trở nên đơn giản bao gồm tránh các vòng lặp lạ, tối thiểu các vòng lặp lồng nhau, tạo và thoát vòng lặp một cách rõ ràng, giữ các housekeeping code ở một vị trí.
\vspace*{3mm}
\noindent Minimizing nesting:
\begin{itemize}
\item Độ dài vòng lặp có thể được tính bởi số dòng của vòng lặp hay số các vòng lặp lồng nhau.
\item Nên tạo các vòng lặp ngắn sao cho có thể quan sát tất cả vòng lặp trong một lần.
\item Hạn chế số lượng các vòng lặp lồng nhau ở con số 3.
\item Nếu vòng lặp dài thì phải thật rõ ràng.
\end{itemize}
Lồng vòng lặp while để in các số nguyên tố nhỏ hơn 100:
\begin{python}
i = 2
while (i < 100):
j = 2
while (j <= i / j):
if i % j == 0:
break
j += 1
if (j > i / j):
print i, " la so nguyen to"
i += 1
\end{python}
\noindent Making entries clearly:
\begin{itemize}
\item Đặt các giá trị khởi tạo cho các biến trong vòng lặp trước khi vào vòng lặp đó.
\item Truy cập vòng lặp chỉ tại một vị trí. Việc này giúp tránh xảy ra lỗi khi ta copy hoặc di chuyển vòng lặp tới một vị trí khác trong mã nguồn. Hơn nữa, khi kích thước chương trình lớn, việc đặt các lệnh khởi tạo trước vòng lặp giúp cho việc thay đổi nó dễ dàng, nhanh chóng hơn.
\item Sử dụng vòng lặp while, for cho vòng lặp vô hạn.
\end{itemize}
\noindent Making exits clearly:
\begin{itemize}
\item Đảm bảo rằng vòng lặp có thể kết thúc.
\item Tạo điều kiện kết thúc rõ ràng cho vòng lặp.
\end{itemize}
Lặp vô hạn:
\begin{python}
var = 1
while var == 1: # lenh nay tao mot vong lap vo han
num = raw_input("Hay nhap mot so: ")
print "So da nhap: ", num
\end{python}
Sử dụng $break$ và $continue$ để điều khiển vòng lặp:
\begin{python}
for letter in 'Python': # vi du thu nhat
if letter == 'h':
break
print 'Chu cai hien tai: ', letter
var = 10 # vi du thu hai
while var > 0:
print 'Gia tri bien hien tai la: ', var
var = var - 1
if var == 5:
break
\end{python}
\begin{python}
for letter in 'Python': # Vi du thu nhat
if letter == 'h':
continue
print 'Chu cai hien tai :', letter
var = 10 # Vi du thu hai
while var > 0:
var = var -1
if var == 5:
continue
print 'Gia tri bien hien tai la :', var
\end{python}
\noindent Keep housekeeping code in one place:
\begin{itemize}
\item Housekeeping code là những lệnh như i++, j = j+1,… để điều khiển vòng lặp. Nên đặt các lệnh này ở đầu hoặc cuối vòng lặp.
\end{itemize}
\subsubsection{KT 16.3. Loop indexes are subjected to a great deal of abuse. Name them clearly, and use them for only one purpose.}
Các chỉ số vòng lặp bị lạm dụng rất nhiều. Đặt tên cho chúng thật rõ ràng và chỉ sử dụng cho một mục đích.
\vspace*{3mm}
\noindent Cách dùng các chỉ số vòng lặp:
\begin{itemize}
\item Dùng biến đếm hoặc biến thứ tự.
\item Biến đếm nên là số nguyên và không nên là số thực dấu phẩy động.
\item Sử dụng các tên biến có ý nghĩa khi làm việc với các vòng lặp lồng nhau (thay vì dùng i, j, k,… thì đặt tên có sự gợi nhớ) -> không mắc phải sử dụng nhầm tên biến hay sử dụng một biến nhiều lần.
\item Hạn chế phạm vi của các biến vòng lặp chỉ trong vòng lặp đó.
\end{itemize}
\subsubsection{KT 16.4.Think through the loop carefully to verify that it operates normally under each case and terminates under all possible conditions.}
Xem xét toàn bộ vòng lặp một cách cẩn thận để kiểm chứng rằng nó đã hoạt động bình thường trong mọi trường hợp và có thể kết thúc dưới mọi điều kiện.
\begin{itemize}
\item Đảm bảo rằng vòng lặp kết thúc được (bằng cách cho chạy thử một số lần lặp với các giá trị cụ thể, xem xét tất cả các trường hợp có thể xảy ra, các điểm kết thúc, các ngoại lệ).
\item Viết các điều kiện kết thúc vòng lặp rõ ràng.
\item Kiểm tra vòng lặp có kết thúc với kết quả như mong muốn hay không.
\end{itemize}
\subsection{Sử dụng chương 17 – Các cấu trúc điều khiển khác}
\noindent Các kỹ thuật tiêu biểu gồm:
\subsubsection{KT 17.1. Multiple returns can enhance a routine's readability and maintainability, and they help prevent deeply nested logic. They should, nevertheless, be used carefully.}
Chương trình con có nhiều lần trả về có thể nâng cao khả năng đọc và bảo trì của chương trình và giúp ngăn ngừa sai sót trong những đoạn lồng nhau. Dù vậy chúng nên được sử dụng cẩn thận.
\begin{itemize}
\item Sử dụng $return$ làm chương trình con dễ đọc hơn.
\item Giúp ngăn chặn việc xảy ra lỗi khi chạy chương trình.
\item Khi dùng $return$ phải cẩn trọng xem xét hết các trường hợp.
\end{itemize}
\begin{python}
def min(x, y):
if x < y:
return x
elif y > x:
return y
else
return x
\end{python}
\subsubsection{KT17.2. Recursion provides elegant solutions to a small set of problems. Use it carefully, too.}
Một tập các vấn đề nhỏ thì được giải quyết bằng phương pháp đệ quy. Phải sử dụng đệ quy thật cẩn thận.
\begin{itemize}
\item Thuật toán đệ quy là thuật toán dựa trên phương pháp chia để trị, chia bài toán thành các bài toán con giải quyết các vấn đề nhỏ hơn bằng cách tự gọi đến chính nó với đầu vào kích thước nhỏ hơn.
\item Sử dụng thuật toán đệ quy là thuận tiện khi các bài toán con dễ xử lý trong khi với các bài toán lớn thì lại phức tạp.
\item Đệ quy là một trong những cách tiếp cận hiệu quả và đơn giản đối với một bài toán khó, giúp cho người đọc code có thể dễ dàng nắm bắt được ý tưởng của lập trình viên.
\end{itemize}
\noindent Chú ý khi sử dụng đệ quy:
\begin{itemize}
\item Đảm bảo rằng đệ quy phải có điểm dừng.
\item Tránh sử dụng đệ quy xoay vòng (ví dụ A gọi B, B gọi C, C gọi A), việc này là nguy hiểm vì dễ dẫn đến chạy vô hạn.
\item Kiểm soát xem stack đang dùng còn đủ dung lượng không.
\item Không nên sử dụng đệ quy cho các bài toán có thể giải quyết dễ dàng bằng vòng lặp nói chung (ví dụ như bài toán tính giai thừa, tìm số Fibonaci,…).
\end{itemize}
\begin{python}
def factorial(n):
if n == 0 or n == 1:
return 1
else
return n * factorial(n - 1)
\end{python}
\subsubsection{KT17.3. In a few cases, gotos are the best way to write code that's readable and maintainable. Such cases are rare. Use gotos only as a last resort.}
Trong một số ít trường hợp, lệnh goto là cách tốt nhất để viết code trở nên dễ đọc và dễ bảo trì. Tuy nhiên các trường hợp này rất hiếm khi xảy ra. Việc sử dụng gôt chỉ là phương án cuối cùng.
\begin{itemize}
\item Goto thường được dùng để xử lý các cấu trúc rẽ nhánh lồng nhau.
\item Lý do goto không được khuyến khích sử dụng là nó có thể được thay thế bởi các lệnh khác (ví dụ break/continue) hoặc gom phần code mà goto chỉ đến vào trong hàm.
\item Trong python không hỗ trợ lệnh goto.
\end{itemize}
\section{\bfseries Tổng hợp kỹ thuật làm việc với các biến}
\subsection{Sử dụng chương 10 -- Các kỹ thuật chung làm việc với biến}
\noindent Các kĩ thuật tiêu biểu gồm:
\subsubsection{KT10.1. Data initialization is prone to errors, so use the initialization techniques described in this chapter to avoid the problems caused by unexpected initial values.}
Việc khởi tạo dữ liệu dễ gặp lỗi, sử dụng kĩ thuật mô tả khởi tạo trong phần này để tránh các vấn đề
không mong muốn gây ra bởi giá trị ban đầu.
\vspace*{3mm}
\noindent {\bfseries Kiểu dữ liệu: }
\begin{itemize}
\item Kiểu số:
\begin{itemize}
\item Kiểu int: Kiểu số nguyên có dấu.
\item Kiểu long: Kiểu số nguyên giới hạn kích cỡ lớn hơn nhiều kiểu int.
\item Kiểu float: Kiểu số thực chấm phẩy động.
\item Kiểu số phức: Có dạng a + bi, khai báo trong Python: complex(x, y)
\end{itemize}
\item Kiểu string.
\item Kiểu list.
\item Kiểu tuple.
\item Kiểu dictionary.
\item Kiểu boolean.
\end{itemize}
Đầu tiên để tạo dữ liệu có hiệu quả là phải biết loại dữ liệu cần tạo. Trải qua bài kiểm tra các
kiểu dữ liệu sẽ giúp bạn xác định được sự hiểu biết của mình về các kiểu dữ liệu.
\subsubsection{KT10.2. Minimize the scope of each variable. Keep references to a variable close together. Keep it local to a routine or class. Avoid global data.}
Giảm thiểu phạm vi của mỗi biến. Giữ những biến có liên quan ở gần nhau. Giữ trong hàm hoặc
lớp ( biến cục bộ ) . Tránh sử dụng biến toàn cục.
\vspace*{3mm}
Ví dụ bài toán sắp xếp:
\begin{python}
#string handler 01
def Funtion_XuLiChuoi01(String):
i=0
L1=str.split(String)
a=len(L1)
for i in range(a):
if i==0:
s=L1[a-1]+" "+L1[0]
if i>0 and i<a-1:
s=s+" "+L1[i]
return s
#string handler 02
def Funtion_XuLiChuoi02(String):
i=0
L1=str.split(String)
a=len(L1)
trungGian=L1[0]
for i in range(a):
if i==1:
s=L1[1]+" ";
if i>1:
s=s+" "+L1[i]
s=s+" "+trungGian
return s
#sap xep
def Funtion_SapXep(list):
a=len(list)
i=0
L1,L2=[],[]
for i in range (a):
L1.append(Funtion_XuLiChuoi01(list[i]))
L1.sort()
for i in range (a):
L2.append(Funtion_XuLiChuoi02(L1[i]))
return L2
list=["Nguyen Van Trung","Cao Thanh Tung", \
"Tong Van Vinh","Ta Quang Tung"]
print("Ban vua nhap: ",list)
listSapXep=Funtion_SapXep(list)
print(listSapXep)
\end{python}
\subsubsection{KT10.3. Keep statements that work with the same variables as close together as possible.}
Giữ các câu lệnh sử dụng biến chung càng gần nhau càng tốt. \\
Ví dụ giải phương trình bậc 2:
\begin{python}
i = 1
while 1:
print("Giai phuong trinh bac hai lan ", i)
a=float(input("Nhap vao a=\n"))
b=float(input("Nhap vao b=\n"))
c=float(input("Nhap vao c=\n"))
if a == 0 :
if b == 0:
if c == 0:
print("Phuong trinh co vo so nghiem")
else:
print("Phuong trinh vo nghiem")
else:
print("Phuong trinh co nghiem x=",-c/b)
else:
denta = b*b - 4*a*c
if denta < 0:
x1 = complex(-b/(2*a),math.sqrt(-denta)/(2*a))
x2 = complex(-b/(2*a),-math.sqrt(-denta)/(2*a))
print("Phuong trinh co nghiem phuc x1=", x1," va x2=", x2)
elif denta == 0:
print("Phuong trinh co nghiem x=",-b / (2*a))
else:
x1=(-b + math.sqrt(denta)) / (2*a)
x2=(-b - math.sqrt(denta)) / (2*a)
print("Phuong trinh co nghiem x1=",x1," va x2=",x2)
string=str.lower(input("Nhap no de thoat:\n"))
if string=="no":
break
else:
i = i + 1
\end{python}
\subsubsection{KT10.4. Early binding tends to limit flexibility but minimize complexity. Late binding tends to increase flexibility but at the price of increased complexity.}
Sự ràng buộc sớm có xu hướng giới hạn tính linh hoạt nhưng giảm bớt sự phức tạp. Sự ràng buộc sau đó có xu hướng tăng tính linh hoạt nhưng cái giá là việc tăng lên của độ phức tạp.
Thời gian ràng buộc là thời gian mà một biến mà giá trị của nó được được buộc với nhau. Có phải chúng được buộc với nhau tại thời điểm code được viết? Sau khi được biên dịch? Khi được nạp? Hay khi chương trình chạy?
\vspace*{3mm}
Một vài thời điểm mà giá trị được buộc vào biến:
\begin{itemize}
\item Thời điểm viết code (Dành cho những giá trị "magic").
\item Thời điểm biên dịch (Dành cho những hằng số được đặt tên).
\item Thời điểm nạp chương trình (Ví dụ như đọc những giá trị từ nguồn bên ngoài chẳng hạn như Windows Registry).
\item Thời điểm tạo một object.
\item Chỉ vừa đúng thời điểm (Như là đọc giá trị mỗi lần một cửa sổ được vẽ lên màn hình).
\item Liên quan đến việc sử dụng các cấu trúc điều khiển rẽ nhánh và vòng lặp…
\end{itemize}
\subsubsection{KT10.5. Use each variable for one and only one purpose.}
Sử dụng mỗi biến cho duy nhất một mục đích.
\noindent Ví dụ: Chương trình minh họa biến tên sum dùng để tính tổng các số nguyên từ 1 đến 10
\begin{python}
sum = 0
for i in range(1, 11):
sum += i
print(sum)
\end{python}
\subsection{Sử dụng chương 11 -- Kỹ thuật đặt tên biến}
\noindent Các kỹ thuật tiêu biểu gồm:
\subsubsection{KT11.1. Good variable names are a key element of program readability. Specific kinds of variables such as loop indexes and status variables require specific considerations.}
Tên biến tốt là thành phần chính quyết định tính dễ đọc của chương trình. Những loại biến cụ thể như chỉ số trong vòng lặp và những biến trạng thái yêu cầu những xem xét cụ thể hơn.
\vspace*{3mm}
Ví dụ biến tên: sql\_request, client\_socket, student\_counter, ...
\subsubsection{KT11.2. Names should be as specific as possible. Names that are vague enough or general enough to be used for more than one purpose are usually bad names.}
Tên nên cụ thể nhất có thể. Những tên mơ hồ hoặc quá tổng quát sẽ có thể được sử dụng nhiều hơn một mục đích, và thông thường đó là những tên tồi.
\vspace*{3mm}
Ví dụ: data, a, b, u, count, ... là những tên tồi.
\subsubsection{KT11.3. Naming conventions distinguish among local, class, and global data. They distinguish among type names, named constants, enumerated types, and variables.}
Quy ước đặt tên phải phân biệt giữa biến cục bộ, biến toàn cục và biến trong hàm. Chúng đồng thời cũng phải giúp phân biệt được kiểu dữ liệu, hằng số, kiểu liệt kê, hay là một biến.
\vspace*{3mm}
\begin{itemize}
\item Kí tự phải bắt đầu là một dấu “\_ ” hoặc một chữ cái.
\item Sau kí tự đầu có thể là nhiều kí tự, hoặc nhiều con số.
\item Python không cho phép sử dụng các kí tự đặc biệt như: @, \#, \$, \%...
\item Tên class bắt đầu với một kí tự viết hoa, các định dạng khác là chữ thường. Ví dụ: Person, StudentInfo,...
\item Nếu đặt tên với việc bắt đầu với một kí tự gạch dưới, ta hiểu rằng đay là một private. Nếu bắt đầu bởi hai kí tự gạch dưới liên tiến, ta hiểu rằng đây là một private mạnh.
\item Biến đếm ta thường dùng là các chữ cái thường như i,j,k. Chiều dài chuỗi có thể dùng size hoặc length, Hằng thường dùng const, final.
\item Tránh đặt tên biến, lớp.. trùng với keyword
\end{itemize}
\subsubsection{KT11.4. Regardless of the kind of project you're working on, you should adopt a variable naming convention. The kind of convention you adopt depends on the size of your program and the number of people working on it.}
Bất kể loại dự án nào mà bạn làm đang làm việc, bạn nên thích thông qua một quy ước đặt tên biến cho dự án đó. Kiểu quy ước nào phụ thuộc vào kích thước chương trình của bạn và số lượng người làm việc với nó.
\subsubsection{KT11.5. Abbreviations are rarely needed with modern programming languages. If you do use abbreviations, keep track of abbreviations in a project dictionary or use the standardized prefixes approach.}
Viết tắt hiếm khi cần thiết với những ngôn ngữ lập trình hiện đại. Nếu bạn sử dụng từ viết tắt, luôn luôn giám sát chúng bằng cách thêm vào từ điển của dự án hoặc sử dụng một tiền tố đã được chuẩn hoá.
\vspace*{3mm}
Ví dụ một số tên viết tắt phổ biến: src, dest, info, inc, dec, ...
\subsubsection{KT11.6. Code is read far more times than it is written. Be sure that the names you choose favor read-time convenience over write-time convenience.}
Code được đọc nhiều hơn rất nhiều được viết. Hãy chắc chắn rằng những tên bạn chọn sẽ ủng hộ sự thuận tiện cho thời điểm đọc hơn là thời điểm viết.
\subsection{Sử dụng chương 12 -- Các kiểu dữ liệu cơ bản}
\noindent Các kĩ thuật tiêu biểu gồm:
\subsubsection{KT12.1. Working with specific data types means remembering many individual rules for each type. Use this chapter's checklist to make sure that you've considered the common problems.}
Làm việc với những kiểu dữ liệu cụ thể nghĩa là phải nhớ nhiều những quy tắc riêng biệt cho từng kiểu. Như những quy tắc dưới đây:
\begin{itemize}
\item Kiểu dữ liệu số tổng quát:
\begin{itemize}
\item Tránh những "magic number", những hằng số xuất hiện ở giữa code mà không có giải thích
\item Có thể code trực tiếp 0, 1 nếu cần thiết
\item Dự tính trường hợp chia cho 0
\item Tránh so sánh khác kiểu giữ liệu
\item Chú ý những cảnh báo của trình dịch
\end{itemize}
\item Kiểu số nguyên:
\begin{itemize}
\item Kiểm tra chia nguyên với chia thực
\item Kiểm tra tràn số
\item Kiểm tra tràn số trong các giá trị trung gian
\end{itemize}
\item Kiểu số thực chấm phẩy động:
\begin{itemize}
\item Tránh cộng và trừ những số có độ lớn khác nhau nhiều
\item Tránh so sánh bằng
\item Dự kiến lỗi làm tròn
\end{itemize}
\item Ký tự và xâu:
\begin{itemize}
\item Tránh những ký tự và xâu "magic"
\item Hiểu rõ ngôn ngữ bạn đang dùng hỗ trợ Unicode ra sao
\item Định rõ khu vực, vùng mà chương trình sẽ được sử dụng
\item Nếu cần hỗ trợ nhiều ngôn ngữ, hãy dùng Unicode
\end{itemize}
\item Biến boolean:
\begin{itemize}
\item Sử dụng kiểu boolean để làm rõ những điều kiện trong chương trình
\item Sử dụng kiểu boolean để đơn giản hoá những test phức tạp
\item Tự tạo một kiểu dữ liệu boolean, nếu như cần thiết
\end{itemize}
\item Kiểu enum:
\begin{itemize}
\item Sử dụng kiểu enum cho tính dễ đọc
\item Sử dụng kiểu enum cho tính tin cậy
\item Sử dụng kiểu enum để cho việc sửa đổi dễ dàng
\item Sử dụng kiểu enum thay thế cho kiểu boolean
\item Sử dụng giá trị ban đầu của enum để cho những giá trị không hợp lệ
\item Xác định rõ phần tử đầu và cuối của enum được sử dụng như thế nào trong toàn bộ project
\item Nếu ngôn ngữ không có kiểu enum thì có thể sử dụng class hoặc từ điển
\end{itemize}
\item Hằng số:
\begin{itemize}
\item Sử dụng hằng số có đặt tên trong khai báo dữ liệu
\item Sử dụng hằng số một cách thống nhất
\end{itemize}
\item Mảng:
\begin{itemize}
\item Đảm bảo rằng chỉ số của mảng ở trong miền cho phép
\item Luôn nghĩ rằng mảng là một cấu trúc tuần tự
\item Nếu mảng là đa chiều, đảm bảo thứ tự của các chỉ số
\item Kiểm tra xem chỉ số khi lặp có đúng như mong muốn
\item Để thêm một phần tử ở cuối mảng
\end{itemize}
\end{itemize}
Ví dụ:
\begin{python}
EPSILON = 0.0001
def are_same(a, b):
return abs(a - b) < EPSILON
\end{python}
\subsubsection{KT12.2. Creating your own types makes your programs easier to modify and more self-documenting, if your language supports that capability.}
Tự tạo một kiểu dữ liệu mới sẽ làm cho chương trình dễ dàng sửa đổi và tăng tính tự mô tả, nếu như ngôn ngữ hỗ trợ khả năng này.
\noindent Một số những chỉ dẫn tự tạo một kiểu dữ liệu của mình:
\begin{itemize}
\item Tạo kiểu dữ liệu với tên hướng đến chức năng của nó
\item Tránh những kiểu dữ liệu đã định nghĩa trước đó
\item Đừng định nghĩa kiểu dữ liệu đã được định nghĩa
\item Định nghĩa kiểu dữ liệu thay thế cho kiểu dữ liệu cũ để tăng tính khả chuyển
\end{itemize}
Trong Python không hỗ trợ tạo kiểu dữ liệu mới.
\subsubsection{KT12.3. When you create a simple type using typedef or its equivalent, consider whether you should be creating a new class instead.}
Nếu tự tạo một kiểu dữ liệu mới bằng typedef hoặc cách tương đương, xem xét việc sử dụng class để thay thế nó.
Ví dụ sử dụng class $StudentID$ để thay thế cho $mssv$ là một số:
\begin{python}
class StudentID:
# mssv
def __init__(self, mssv):
self.mssv = mssv
\end{python}
\subsection{Sử dụng chương 13 – Các kiểu dữ liệu đặc biệt}
\noindent Các kĩ thuật tiêu biểu gồm:
\subsubsection{KT13.1. Structures can help make programs less complicated, easier to understand, and easier to maintain.}
Kiểu dữ liệu có cấu trúc sẽ giúp chương trình giảm độ phức tạp, dễ dàng để hiểu, để duy trì nó hơn.
\noindent Một số những lưu ý khi sử dụng kiểu dữ liệu có cấu trúc:
\begin{itemize}
\item Sử dụng kiểu dữ liệu có cấu trúc để làm rõ mối quan hệ giữa các dữ liệu
\item Sử dụng để đơn giản hoá những thủ tục lên khối dữ liệu
\item Sử dụng để đơn giản hoá tham số đầu vào của hàm
\item Sử dụng để giảm bớt việc bảo trì chương trình
\end{itemize}
Ví dụ:
\begin{python}
class Person:
def __init__(self, name, age, phone):
self.name = name
self.age = age
self.phone = phone
def print_person(person):
print("Ho ten: " + person.name)
print("Tuoi: " + person.age)
print("So dien thoai: " + person.phone)
person = Person("Ta Quang Tung", 19, 123)
print_person(person)
\end{python}
\subsubsection{KT13.2. Whenever you consider using a structure, consider whether a class would work better.}
Khi sử dụng một kiểu giữ liệu có cấu trúc, xem xét liệu rằng class sẽ tốt hơn.
Ví dụ:
\begin{python}
http_request = {'method': 'get', 'url':'sis.hust.edu.vn', \
'id': 20154280}
def send_http_request(http_request):
...
\end{python}
Sẽ tốt hơn nếu được thay thế bằng:
\begin{python}
class HttpRequest:
def __init__(self, method, url, id):
self.method = method
self.url = url
self.id = id
def send(self):
...
\end{python}
\subsubsection{KT13.3. Pointers are error-prone. Protect yourself by using access routines or classes and defensive-programming practices.}
Con trỏ là kiểu dữ liệu dễ dàng gặp lỗi khi sử dụng. Bảo vệ bản thân bằng việc sử dụng hàm hoặc class khi muốn truy cập nó, hoặc sử dụng kỹ thuật lập trình "tự phòng thủ".
\vspace*{5mm}
\noindent Những yêu cầu khi sử dụng biến con trỏ:
\begin{itemize}
\item Sử dụng một kiểu con trỏ rõ ràng thay vì kiểu con trỏ mặc định.
\item Tránh cast kiểu dữ liệu con trỏ.
\item Trong C, nếu bạn sử dụng dấu * với tham số ở hàm, luôn nhớ rằng giá trị có thể truyền ngược lại khi gọi hàm. Đồng thời khi bạn muốn truyền ngược lại giá trị, chắc chắn rằng phải có ít nhất một dấu sao trong một câu lệnh gán.
\item Sử dụng sizeof() để xác định kích thước của biến khi cấp phát bộ nhớ cho nó.
\end{itemize}
Trong python không có kiểu con trỏ.
\subsubsection{KT13.4. Avoid global variables, not just because they're dangerous, but because you can replace them with something better.}
Tránh dử dụng biến toàn cục, không phải chỉ vì nó nguy hiểm mà còn bởi vì bạn có thể thay thế nó bằng những cách thức tốt hơn nhiều.
\vspace*{5mm}
\noindent Những vấn đề chính khi sử dụng kiểu dữ liệu toàn cục:
\begin{itemize}
\item Vô tình thay đổi kiểu dữ liệu toàn cục.
\item Có thể có những lỗi kì quặc khi sử dụng "tên thay thế" cho biến toàn cục. Chẳng hạn như việc truyền đồng thời tham số vào hàm là biến toàn cục, cũng như sử dụng biến toàn cục trong chính hàm.
\item Vấn đề code được sử dụng nhiều lần trong khi nó truy cập đến biến toàn cục, chẳng hạn như lời gọi đệ quy, hoặc trong trường hợp đa luồng.
\item Tính tái sử dụng của Code bị cản trở bới kiểu toàn cục.
\item Thứ tự khởi tạo không xác định khi sử dụng kiểu toàn cục.
\item Tính module hoá và khả năng kiểm soát code bị huỷ hoại bởi sử dụng kiểu toàn cục.
\end{itemize}
\noindent Những lý do để sử dụng biến toàn cục:
\begin{itemize}
\item Bảo tồn những giá trị toàn cục, ví dụ bảng dữ liệu mà tất cả các hàm sử dụng.
\item Liệt kê những giá trị hằng số, trong những ngôn ngữ không hỗ trợ hằng số như Python, Perl.
\item Sử dụng như kiểu dữ liệu enum, như trong Python.
\item Loại bỏ những dữ liệu "lang thang". Ví dụ như khi có 3 hàm, gọi lần lượt lẫn nhau theo đúng thứ tự 1, 2, 3.
Hàm 1 và hàm 3 sử dụng cùng một object, nhưng hàm 2 thì không. Nếu truyền qua tham số thì ta vẫn phải truyền nó qua hàm 2, đó là dữ liệu "lang thang". Sử dụng biến toàn cục sẽ loại bỏ những dữ liệu này.
\end{itemize}
\noindent Sử dụng biến toàn cục chỉ khi nó là phương pháp cuối cùng.
\begin{itemize}
\item Bắt đầu bởi tạo một biến cục bộ và chỉ thay đổi nó thành toàn cục khi thực sự cần thiết.
\item Phân biệt giữa biến toàn cục và biến trong class.
\item Sử dụng những hàm, thủ tục để truy cập.
\end{itemize}
\noindent Làm thế nào để giảm bớt những rủi ro khi sử dụng biến toàn cục:
\begin{itemize}
\item Triển khai một quy ước đặt tên để làm cho biến toàn cục trở nên hiển nhiên.
\item Tạo một danh sách các chú thích tốt cho tất cả các biến toàn cục.
\item Đừng sử dụng biến toàn cục cho các kết quả trung gian.
\item Đừng giả vờ rằng bạn không sử dụng biến toàn cục bằng cách đặt tất cả dữ liệu vào một object rất lớn và truyền nó khắp mọi nơi.
\end{itemize}
\subsubsection{KT13.5. If you can't avoid global variables, work with them through access routines. Access routines give you everything that global variables give you, and more.}
Nếu không thể tránh khỏi việc sử dụng biến toàn cục thì nên sử dụng những hàm, thủ tục để truy cập nó thay vì truy cập trực tiếp.
Truy cập nhờ hàm, thủ tục sẽ cho bạn mọi thứ như khi sử dụng biến đó trực tiếp, và thêm nhiều hơn thế nữa.
\vspace*{5mm}
\noindent Lợi ích của việc sử dụng hàm truy cập biến toàn cục:
\begin{itemize}
\item Bạn có thể tập trung hoá việc truy cập biến toàn cục. Nếu bạn nghĩ ra một cách thức truy cập mới cho dữ liệu đang sử dụng, khi đó bạn không phải thay đổi code nơi mà dữ liệu được sử dụng, chỉ cần thay đổi code trong hàm truy cập.
\item Có thể đảm bảo rằng tất cả các truy cập đến biến toàn cục được "rào chắn".
\item Bạn sẽ được lợi nhờ việc che giấu thông tin tự động.
\item Hàm truy cập sẽ giúp dễ dàng cho việc chuyển sang kiểu dữ liệu trừu tượng.
\end{itemize}
\noindent Làm thế nào để sử dụng hàm truy cập:
\begin{itemize}
\item Yêu cầu tất cả các truy cập biến phải thông qua hàm truy cập.
\item Đừng chỉ vứt toàn bộ những biến toàn cục vào một cái thùng.
\item Sử dụng cơ chế khoá để bảo vệ biến toàn cục khi lập trình đa luồng.
\item Xây dựng thêm một mức trừu tượng hoá vào trong hàm truy cập.
\item Giữ tất cả các truy cập của dữ liệu ở cùng một mức trừu tượng, đừng cho phép sử dụng nhiều mức trừu tượng để truy cập giữ liệu.
\end{itemize}
Ví dụ về hàm truy cập kết hợp cơ chế đồng bộ:
\begin{python}
__counter = 0
__mt = mutex()
def get_counter():
__mt.lock()
tmp = __counter
__mt.unlock()
return tmp
def set_counter(value):
__mt.lock()
__counter = value
__mt.unlock()
def inc_counter():
__mt.lock()
__counter += 1
__mt.unlock()
\end{python}
% Begin section
\section{\bfseries Tổng hợp kỹ thuật xây dựng chương trình, hàm, thủ tục}
\subsection{Sử dụng chương 5 -- Các kỹ thuật thiết kế chương trình phần mềm -- Design in Construction}
\noindent Các kĩ thuật tiêu biểu gồm:
\subsubsection{KT5.1. Software's Primary Technical Imperative is managing complexity. This is greatly aided by a design focus on simplicity.}
Yêu cầu kỹ thuật chính đối với phần mềm là kiểm soát sự phức tạp. Nó được hỗ trợ rất lớn bởi thiết kế tập trung vào sự đơn giản.
\vspace*{3mm}
\noindent {\bfseries Tầm quan trọng của việc quản lý sự phức tạp trong phát triển phần mềm:}
Khi một cuộc khảo sát về những dự án phần mềm báo cáo nguyên nhân dẫn đến thất bại, họ thường không xác định rõ là những vấn đề về mặt kĩ thuật là nguyên nhân chính gây nên thất bại của dự án. Một dự án thất bại phần lớn bởi vì yêu cầu không rõ ràng, lập kế hoạch không đầy đủ, và kiểm soát kém chặt chẽ. Nhưng khi một dự án thất bại vì lý do chính là kỹ thuật, lý do thường sẽ là không thể kiểm soát được sự phức tạp bên trong phần mềm đó. Phần mềm có thể được phép phát triển đến mức cực kì phức tạp mà không ai có thể hiểu thực sự nó đang làm gì. Khi dự án chạm mức không một ai có thể thực sự hiểu ảnh hưởng của những đoạn code này trong vùng này có tác độngđộng đến đoạn code trong vùng khác như thế nào, sự tiến triển của phần mềm sẽ bị kìm hãm xuống một nửa.
Kiểm soát sự phức tạp của phần mềm là vấn đề kỹ thuật quan trọng nhất trong phát triển phần mềm.
Sự phức tạp không phải là mới trong công việc phát triển phần mềm. Nhà tiên phong trong khoa học tính toán Edsger Dijkstra đưa ra một luận điểm rằng: tính toán chỉ thực sự chuyên nghiệp khi một bộ óc có trách nhiệm phải mở rộng một dữ liệu từ một bit đến một vài megabyte, một tỉ lệ tầm 1 / $10^9$, hay 9 bậc về độ lớn (Dijkstra 1989). Tỉ lệ đó thật đáng kinh ngạc, Dijkstra đặt nó trong câu nói: "Compared to that number
of semantic levels, the average mathematical theory is almost flat. By evoking
the need for deep conceptual hierarchies, the automatic computer confronts us
with a radically new intellectual challenge that has no precedent in our history." -- Nếu so sánh về số lượng mức ngữ nghĩa, trung bình một lý thuyết toán học gần như bằng phẳng. Bởi việc gợi nên sự cần thiết cho "hệ thống phân cấp khái niệm rất nhiều lớp", máy tính tự động thách thức chúng ta với một thử thách trí tuệ hoàn toàn mới, cái mà không hề có tiền lệ trong lịch sử. Tất nhiên phần mềm đã ngày càng trở nên phức tạp, và tỉ lệ của Dijkstra có thể là 1 / $10^{15}$ ngày hôm nay.
Dijkstra cho rằng không một ai có một bộ óc đủ lớn để chứa đựng một phần mềm máy tính hiện đại, nghĩa là một developer không nên cố gắng nhồi nhét toàn bộ phần mềm vào óc mình tại một thời điểm. Chúng ta phải cố gắng tổ chức chương trình bằng một cách nào đó để tại một thời điểm, ta có thể chỉ cần tập trung vào một phần của chương trình.
\subsubsection{KT5.2. Simplicity is achieved in two general ways: minimizing the amount of essential complexity that anyone's brain has to deal with at any one time, and keeping accidental complexity from proliferating needlessly.}
\noindent {\bfseries Làm thế nào chống lại sự phức tạp}
Có 3 nguồn của sự tốn kém quá mức, sự thiết kế không hiệu quả:
\begin{itemize}
\item Một lời giải phức tạp cho một vấn đề đơn giản.
\item Một lời giải đơn giản, không chính xác cho một vấn đề phức tạp.
\item Một lời giản phức tạp, không hợp lý cho một vấn đề phức tạp.
\end{itemize}
Như là Dijkstra đã chỉ ra, phần mềm hiện đại bản thân nó là phức tạp, không kể bạn có cố gắng như thế nào, bạn chắc chắn sẽ phải động chạm vào một vài mức của sự phức tạp mà nó là cái vốn có của những vấn đề thực tế.
Hai cách tiếp cận để kiểm soát sự phức tạp:
\begin{itemize}
\item Tối thiểu hoá sự phức tạp "thiết yếu" cho bất kì ai phải động đến, tại bất kì thời điểm nào.
\item Giữ cho sự phức tạp "tình cờ" tránh khỏi việc trở nên không cần thiết.
\end{itemize}
\subsubsection{KT5.3. Design is heuristic. Dogmatic adherence to any single methodology hurts creativity and hurts your programs.}
Thiết kế là một công việc heuristic. Bất kì một phương pháp nào tuân thủ theo cách độc đoán, giáo điều sẽ phá hoại sự sáng tạo và phá hoại chương trình của bạn.
\vspace*{3mm}
\noindent {\bfseries Những thách thức trong thiết kế phần mềm: }
\begin{itemize}
\item Thiết kế là một "vấn đề mờ" (wicked problem) -- "vấn đề mờ" là những vấn đề mà có thể định nghĩa rõ ràng chỉ khi bởi giải quyết nó, hoặc một phần của nó. Một trong những sự khác biệt giữa chương trình bạn phát triển ở trường và cái mà bạn phát triển khi chuyên nghiệp đó là vấn đề thiết kế được giao ở trường hiếm khi mơ hồ.
\item Thiết kế là một quá trình luộm thuộm. Kết quả sau khi hoàn tất thiết kế phần mềm là tổ chức rõ ràng và sạch sẽ. Nhưng quá trình được sử dụng khi phát triển bản thiết kế gần như không "tươm tất" như kết quả cuối cùng. Mắc lỗi là điểm cần thiết của công việc thiết kế. Sự luộm thuộm đến từ việc khó để biết khi nào bản thiết kế của chúng ta đã đủ tốt. Việc thiết kết là một công việc "kết thúc mở", thông thường chỉ kết thúc khi bạn hết thời gian.
\item Thiết kế là về việc đánh đổi và sự ưu tiên: Phần chính của một nhà thiết kế là phải đánh giá những đặc tính của phần mềm và cân bằng giữa những đặc tính đó.
\item Thiết kế liên quan đến sự hạn chế: Sự ràng buộc trong giới hạn tài nguyên khi xây dựng phần mềm thúc đẩy sự đơn giản hoá trong lời giải, cái mà cuối cùng sẽ cải thiện lời giải của vấn đề.
\item Thiết kế là một công việc không xác định: Nếu bạn cho ba người riêng biệt cùng thiết kế một phần mềm, họ chắc chắn sẽ trả về ba bản thiết kế gần như hoàn toàn khác nhau, và có thể tất cả số chúng đều hoàn toàn được chấp nhận.
\item Thiết kế là một quá trình heuristic: Bởi vì thiết kế là công việc không xác định, các kỹ thuật thiết kế có xu hướng "heuristic" -- Không bao giờ một phương thức có thể được áp dụng chính xác trong tất cả các trường hợp. Không có công cụ nào là đúng cho mọi thứ.
\item Thiết kế là "sự xuất hiện": Thiết kế không phải được hình thành đầy đủ từ bộ óc của một người, nó liên quan và được cải thiện dần dần bởi sự xem xét, sử thảo luận, kinh nghiệm khi viết code hoặc sửa lại code.
\end{itemize}
\subsubsection{KT5.4. Good design is iterative; the more design possibilities you try, the better your final design will be.}
Một bản thiết kế tốt là quá trình lặp đi lặp lại, càng nhiều những khả năng thiết kế mà bạn thử, kết quả thiết kế cuối cùng của bạn sẽ càng tốt.
\vspace*{3mm}
\noindent {\bfseries Những đặc trưng mong muốn của một bản thiết kế:}
\begin{itemize}
\item Sự phức tạp tối thiểu.
\item Dễ dàng bảo trì.
\item Tối thiểu hoá sự kết nối.
\item Tính mở rộng.
\item Tính tái sử dụng.
\item "Lượng đầu vào" cao -- "Lượng đầu vào" ở đây ám chỉ việc một class được các class khác sử dụng như thế nào. "Lượng đầu vào" cao nghĩa là hệ thống phải có các class hữu ích được sử dụng rộng khắp chương trình.
\item "Lượng đầu ra" thấp hoặc trung bình -- "Lượng đầu ra" ở đây ám chỉ việc một class sử dụng số class khác bao nhiêu.
"Lượng đầu ra" cao (nhiều hơn khoảng 7) chỉ định rằng class đó sử dụng một lượng lớn các class khác, và có thể gây nên sự phức tạp quá mức.
\item Tính khả chuyển.
\item Sự "nghèo nàn" -- "nghèo nàn" ở đây nghĩa là hệ thống không có những phần dư thừa.
\item Sự phân tầng -- Thiết kế hệ thống sao cho bạn có thể nhìn nó ở một mức phân cấp mà không phải đào sâu vào các mức khác.
\item Sử dụng những kĩ thuật đã chuẩn hoá.
\end{itemize}
\vspace*{3mm}
\noindent {\bfseries Sự lặp lại trong thiết kế:}
Thiết kế là một quá trình lặp đi lặp lại: Bạn sẽ không chỉ đi từ điểm A đến điểm B, bạn sẽ đi từ điểm A tới B và quay ngược trở lại A.
Với mỗi lần lặp lại và thử với cách tiếp cận khác nhau, bạn sẽ nhìn vấn đề dưới góc nhìn ở cả mức thấp và mức cao. Bức tranh lớn mà bạn nhận được với những vấn đề ở mức cao sẽ giúp bạn đặt những vấn đề mức thấp ở đúng vị trí. Những chi tiết của vấn đề mức thấp cung cấp cho bạn nền tảng vững chắc cho những quyết định ở mức cao. Hoán đổi việc xem xét giữa mức thấp và mức cao là khá khó khăn, nhưng nó là thiết yếu đối với việc thiết kế hiệu quả. Khi tạo ra bản thiết kế đầu tiên mà có vẻ đủ tốt, đừng nên dừng lại. Nỗ lực lần thứ hai sẽ gần như luôn luôn tốt hơn lần đầu.