豆技巧到底实用不实用呢?

豆知识是指各种很琐碎、不成系统、缺乏逻辑连贯性的零碎条目知识。
像「随便在自己启动的Thread中更新UI内容会导致AndroidAPP当机喔!」这就是种豆知识。

那...豆技巧呢?
最知名的豆技巧:请计算连续数字M~N的总和。
菜鸟会乖乖用矩阵计算答案,(如果这是场考试,这题就会拿零分。)

int sum = 0
for(int i = M ; i <= N ;i++){
  sum += i;
}

但正确答案是用梯形面积的数学公式去计算。

int sum = (M + N)(N - M)/2;

明明需要计算「连续数字M~N的总和」的情境,在现实中几乎是可遇不可求,但某些(还算常见的)程序设计教育(藉由这种考题)会让工程师以为「正确使用矩阵、习惯使用矩阵、坚定使用矩阵,是徒劳无益且多余的行为。」

一件很明确的事情有个很明确的答案,这个答案就是豆技巧。既然都是种「豆」,豆技巧一样也是各种很琐碎、不成系统、缺乏逻辑连贯性的零碎条目程序。

一个物件的「建构式」是种豆知识,但很多物件的「建构式」摆在一起却可能有种「系统」与「逻辑连贯性」。用建构式做例子会有点狭隘,在礼拜五的晚上,我一时也想不到(也没那个力气寻找)更好的例子了。

但有些豆技巧还真的挺重要,而且变化起来很方便,就不会「只能用在考试中」。

像「把十进位转换成十六进位」。


String hex(int n){
  String hexString = "0123456789ABCDEF";
  return hextString.getCharAt(n);
}

上面这个函数还需要补足一些「大於16」的逻辑判断和递回应用。
hexString其实就是个「0~F」的字元符号矩阵,字元在矩阵中的位置刚好对应了「0~15」。
如果可以从中看出「不需要判断」「直接用参数决定要取用哪些东西」的设计概念,那可以应用在很多地方。

像下面这样的例子...


void test(int index){
   if(index == 0){
    ...
   }
   else if(index == 1){
    ...
   }
   else if(index == 2){
    ...
   }
}

范例中已经很「体贴」的使用了0/1/2...作为index的判断值,但现实中这样写程序是作死!
首先,为了方便使用这个test函数,(假设它是个library/module,写它的人未必是用它的人,)就需要让使用者知道可以传入哪些数值,所以会有一排精准定义过名称(看了就知道干嘛)的参数在物件中。
例如.......

final int Test_Index_0 = 0;
final int Test_Index_1 = 1;
final int Test_Index_2 = 2;

这样,使用者就知道可以带这些参数进test中。(名字当然可以取的更好懂,例如直接表达这个参数的目的,例如「Test_Index_Init」「Test_Index_Loop」这种形式。)

接着,这样写出来的程序很冗长,很难扩充跟维护。

像「如果要新增几个Test_Index_3/Test_Index_4/Test_Index_6(跳过Test_Index_5)
」呢?

将if..else改成switch?这野心太小。

首先要扩充参数...

final int Test_Index_0 = 0;
final int Test_Index_1 = 1;
final int Test_Index_2 = 2;
final int Test_Index_3 = 3;
final int Test_Index_4 = 4;
final int Test_Index_6 = 6;

我们导入设计模式中的策略模式吧!先定义一个策略模式...

interface TestFunction{
  void func(int v);
}

class Test0 implements TestFunction{...}
class Test1 implements TestFunction{...}
class Test2 implements TestFunction{...}
class Test3 implements TestFunction{...}
class Test4 implements TestFunction{...}
class Test6 implements TestFunction{...}

然後来重新修改刚刚的test函数...


TestFunction[] funcs = {
   new Test0(), new Test1(), new Test2(), new Test3(), new Test4(), null, new Test6()
}

void test(int index, int v){
   if(funcs[index] != null)
     funcs[index].func(v);
}

这样,程序就会变得很好扩充。未来即使要再新增更多对应功能,也只需要将新功能用物件实作後,在funcs中新增该物件的实体即可让新功能被test函数使用。

(看过专案起始的工程师不懂这个技巧,就只使用switch,然後接手的工程师就把扩充维护给搞砸搞烂了......)


<<:  [Day9] Git学习笔记- cherry-pick & 使用 VSCode作为 GUI

>>:  初次遇见 .NET

[Day 12] 第一主餐 pt.5-MySQL Django一起串联,就是这麽简单

在昨天我们成功透过url取得我们的django连接以及内容了 今天我们要再回到虚拟环境,架设MySQ...

Day07:部门与工程团队间协作的技巧(上)

一、前言   所谓的团队合作,我想最重要的就是如何沟通与使用有效之协作工具!沟通属於较偏人性与软性之...

25 | 【进阶教学】什麽是 WordPress 区块小工具?

由於 WordPress 是不停改进的 CMS 系统,它们在 2021 年的 WordPress ...

Gulp npm install 中的 --save 与 --save-dev 差异 DAY94

npm install --save (产品用) npm install --save-dev (开...

[Day15] Boxenn 实作 Repository & Query

Repository 将 source wrapper 、 record mapper 、 fact...