iT邦幫忙

0

探究優化以及coding風格-附上例子 (歡迎各路好手,來深度討論)

  • 分享至 

  • xImage

前情提要

今天看到一段代碼
發現在調用函式的使用手段 用了一個我沒想過的手法
先請看下面這邊

程式碼

function selfPush(){
    jQuery.ajax({
        type: "POST",
        data: {
            rtecontent: "[div]"+content+"[/div]",
            pwd: getVal("pwd"),
            type: getVal("type"),
            code: getVal("code"),
            subbsn: getVal("subbsn"),
            title: getVal("title"),
            sign: getVal("sign"),
            ptype: getVal("ptype"),
            bbsign: getVal("bbsign"),
            ccsign: getVal("ccsign"),
        },
   
function getVal(input) {
	return document.getElementsByName(input)[0].value;
}

想法

這邊的重點是我自己來寫這段,並不會有這樣子風格的寫法產生!
看到這招,覺得格外有趣◑ω◐。

如果是我的操作 程式碼的風格會長怎樣?

依照以前學過來的經驗 我應該會把這些data設定為變數
這邊我就寫原生的JS就好 當然用JQuery是差不多意思
如下

            pwd=document.getElementsByName(pwd)[0].value;
            type=document.getElementsByName(type)[0].value;
            code=document.getElementsByName(code)[0].value;
            subbsn=document.getElementsByName(subbsn)[0].value;
            title=document.getElementsByName(title)[0].value;
            sign=document.getElementsByName(sign)[0].value;
            ptype=document.getElementsByName(ptype)[0].value;
            bbsign=document.getElementsByName(bbsign)[0].value;
            ccsign=document.getElementsByName(ccsign)[0].value;

ajax的裡面部分
其實光是寫到上面變數 各位看下來應該都懂 但我還是貼出來示意XD
就像是如下

            pwd: pwd;
            type: type;
            code: code;
            subbsn: subbsn;
            title: title;
            sign: sign;
            ptype: ptype;
            bbsign: bbsign;
            ccsign: ccsign;

風格或是效能?

發現到這招覺得「程式碼優化」這個議題可以好好研究!!

因為這樣對比下來,我發現getVal的這種手段頗聰明的。
那我好奇的是這樣子是否比較簡潔,又另一個議題是在效能上是否會有差別?

各位會用什麼名詞或觀念解釋這樣子的coding技巧?
在寫程式的時候也有相似的其他招數嗎?

歡迎各位前輩來討論這樣子寫的風格,以及效能,進行深入探討與分析。

看更多先前的討論...收起先前的討論...
froce iT邦大師 1 級 ‧ 2023-03-25 12:40:22 檢舉
本想說些什麼,還是算了。
嗯,你高興的話就這樣吧...
fillano iT邦超人 1 級 ‧ 2023-03-25 12:54:09 檢舉
可以參考:https://zh.wikipedia.org/zh-tw/%E4%B8%80%E6%AC%A1%E4%B8%94%E4%BB%85%E4%B8%80%E6%AC%A1

DRY 並不僅可以用在物件導向程式設計上就是了,簡單地把要重複做的事情抽出成函數/方法來避免重複,是最基本的原則之一,永遠用得到。
謝謝樓上兩位大師,提出DRY太感謝,的確有看到這個風格。
學到很多。
ShawnL iT邦新手 1 級 ‧ 2023-03-25 14:43:22 檢舉
延續上面的補充,DRY 是一種常用的心法之一,但有時候重複也是一種設計,那經典 Clean Code 一書為例,作者也有說明他是作為一種學派並不是他那種方式就一定好。

所以進一步來說,所謂的好不好就我經驗來說,其實需要各種因素下去考量,比方打包工具的支援、使用的框架(框架本身理念是命令式、宣告式)、專案調整頻率、專案規模大小等等⋯⋯甚至團隊成員的共識都會影響作法的「合適程度」。

那要達到什麼程度才算比較好,除了靠經驗外、有需求來時被當初設計迴力鏢打到⋯⋯等等等,比較重要的一點是這樣設計出來的心歷路程是否能說服得了團隊成員,否則怎麼設計都會有對應的一些缺陷。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
2
㊣浩瀚星空㊣
iT邦大神 1 級 ‧ 2023-03-25 13:00:49
最佳解答

嘛~~~

這個其實還真不知道該如何說。
雖然你說 getVal 很好。但其實我倒是覺得還好。
不能說它不好。只是還不到位。

不過我想你還未學好VUE、React、Angular這一類的前端框架。
你會發現你說的getVal。根本是個屁。

所以我大概可以理解 froce 可能想說的話。
不過我也會借用他的話。
其實你高興就好。

但你要知道一件事。你目前觸碰到的東西。都還只在邊邊。
在你認為這樣寫法很好不錯的感覺。
你就會停止進步了。
其實有更方便更好的寫法存在。

看更多先前的回應...收起先前的回應...

謝謝大師的開導,我的確正在學習vue呢◑ω◐
原來這招沒什麼用,只是覺得挺有趣的。
看來是我大驚小怪了呢~~

froce iT邦大師 1 級 ‧ 2023-03-25 13:35:10 檢舉
  1. DRY以外還要注意一件事,就是你有沒有想過,[0]這操作是不是永遠取的到?

  2. 符合DRY的話,定這個getVal的函數,他用途就只是取value,萬一你還要對這個元素做操作呢?

下面這種操作可是很常見的

    jQuery.ajax({
        type: "POST",
        data: {
            rtecontent: "[div]"+content+"[/div]",
            pwd: getVal("pwd"),
            type: getVal("type"),
            code: getVal("code"),
            subbsn: getVal("subbsn"),
            title: getVal("title"),
            sign: getVal("sign"),
            ptype: getVal("ptype"),
            bbsign: getVal("bbsign"),
            ccsign: getVal("ccsign"),
        },
        success: function(){
            ....
            // 譬如清空密碼槽、disable、隱藏密碼槽
        }
        })

這樣的話你用getVal有什麼特殊意義嗎?
還不如用個

const pwd = $('#pwd')
// 你後面要用就能  pwd.val()就好,元素也能復用
    jQuery.ajax({
        type: "POST",
        data: {
            pwd: pwd.val(),
        },
        }).done(function(){
            pwd.hide()
        })
  1. 然後既然是要存取的欄位,除非你是用vue之類的框架,為何不乖乖給ID呢?要不然像下面一樣整個form去取鍵值對也好。

反正光一眼瞄過去能吐槽的就三大點了...

@froce 感謝解答!

關於第一點我的確有好奇,這樣寫是否都能抓到,謝謝提出。
關於第二點我真的沒想到有這樣子的可能,的確是超級漏洞,是個問題。
關於第三點的話,框架我真的是還沒摸到邊邊,完全有道理。

大師果然有經驗跟見解,是我大驚小怪了。
以為這是個聰明的小巧招,實則只是普普通通的一般寫法。
我把JS看的太淺了。

非常感謝,學習到很多,心態上也是(。◕∀◕。)。

這次選您為最佳解答,也感謝froce精闢的戳中要害!
非常有幫助。

0
alien663
iT邦研究生 5 級 ‧ 2023-03-25 13:36:42

我在使用React之前是這樣做的,我寫了一個Collector,給他Form之後會幫我蒐集成我要的資料格式。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
    <title>Document</title>
</head>
<body>
    <form id="demoform">
        <div> 
            <p>normal input</p>
            <label>帳號<input name="account"></label>
            <br>
            <label>密碼<input name="password"></label>
            <br>
            <label>行星<input name="planet"></label>
        </div>

        <div> 
            <p>radio button</p>
            <label><input type="radio" name="goal" value="lv-426">LV-426</label>
            <label><input type="radio" name="goal" value="lv-427">LV-427</label>
            <label><input type="radio" name="goal" value="lv-428">LV-428</label>
            <label><input type="radio" name="goal" value="lv-429">LV-429</label>
        </div>

        <div>
            <p>check box</p>
            <label><input type="checkbox" name ="tool" value="gun">gun</label>
            <label><input type="checkbox" name ="tool" value="sword">sword</label>
            <label><input type="checkbox" name ="tool" value="aox">aox</label>
            <label><input type="checkbox" name ="tool" value="money">money</label>
        </div>

        <div>
            <p>selector</p>
            <select name="pet">
                <option value="">請選擇你最愛的寵物</option>
                <option value="Facehugger">Facehugger</option>
                <option value="Dog">Dog</option>
                <option value="Cat">Cat</option>
                <option value="Hamster">Hamster</option>
                <option value="Parrot">Parrot</option>
                <option value="Spider">Spider</option>
                <option value="Goldfish">Goldfish</option>
            </select>
        </div>

        <div>
            <p>text area</p>
            <label><textarea name="remark" style="width:300px;height:150px;" ></textarea></label>
        </div>
    </form>
    <script>
        function collectData(formID){
            var formdata = $(formID).serializeArray()
            var columns = Array.from(new Set(formdata.map(item => {return item.name})))
            var new_data = columns.map( item => {
                let temp_ary = formdata.filter( st => {return st.name === item})
                let temp_obj = new Object()
                temp_obj[item] = temp_ary.length > 1 ? temp_ary.map(ck => {return ck.value}) : temp_ary[0].value
                return temp_obj
            })
            console.log(new_data)
        }
    </script>
    <button onclick="collectData('#demoform')">click me to collect data</button>
</body>
</html>

突然看到一個好懷念的函式 serializeArray 。
很久沒看到它了。

感謝您出來分享,各位願意討論都對我非常有幫助!

0
Nick
iT邦新手 5 級 ‧ 2023-03-26 16:37:18

在寫程式的時候也有相似的其他招數嗎?
我喜歡使用 Lazy Loading 的方式宣告不常使用到的變數.

// class 中宣告的屬性
private $_variables = array();

下方使用

// 這是個PHP示範 
/**
     * This is a private method used to handle variables.
     *
     * @param string $variable The variable name.
     * @return mixed Returns the variable value.
     */
    private function _variable(string $variable): mixed
    {
        if (isSet($this->$variable)) {
            return $this->$variable;
        }
        $fn = sprintf("%s_%s", '_get_variable', $variable);

        $this->$variable = $this->$fn();

        return $this->$variable;
    }


    /**
     * This magic method is used to get the value of a property that was not declared explicitly.
     *
     * @param string $name The property name.
     * @return mixed|null Returns the value of the property if it exists or null otherwise.
     */
    public function __get(string $name): mixed
    {
       return $this->_variables[$name] ?? null;
    }


   /**
    * This magic method is used to set the value of a property that was not declared explicitly.
    *
    * @param string $name The property name.
    * @param mixed $value The value to set for the property.
    * @return void
    */
    public function __set(string $name, mixed $value): void
    {
       $this->_variables[$name] = $value;
    }

這時候只要宣告一個 function

private function _get_variable_test(): string
{
    return "this is test";
}

我就可以使用 $this->_variable('test') 來得到我所需要的 return.

風格或是效能?
剛開始寫程式的時候都會希望能有什麼新潮或很騷的方式去寫code.
其實後面, 不管是什麼方式, 減少 code review 跟 Debug 時間才是最重要的.
...除非你是寫底層語言.

題外話
現在框架大部分都用 axios 了吧@@

0
Vader
iT邦研究生 4 級 ‧ 2023-03-27 11:27:34

可以將表單數據打包成一個對象,而不是分別傳遞每個參數。這樣可以使代碼更簡潔,易於維護和擴展

function selfPush() {
    const formData = {
        rtecontent: `[div]${getVal('content')}[/div]`,
        pwd: getVal('pwd'),
        type: getVal('type'),
        code: getVal('code'),
        subbsn: getVal('subbsn'),
        title: getVal('title'),
        sign: getVal('sign'),
        ptype: getVal('ptype'),
        bbsign: getVal('bbsign'),
        ccsign: getVal('ccsign'),
    };
    
    jQuery.ajax({
        type: 'POST',
        data: formData,
        // ...
    });
}
0
sixwings
iT邦研究生 4 級 ‧ 2023-04-03 00:34:27

你貼的程式碼看起來是一段把 form 表單內的 input 收集起來透過 jQuery Ajax 送出的程式碼,建議可以把 HTML 部分的內容也補齊,這樣你的問題會完整一些,其他人就不用透過通靈的方式去猜測 HTML 的內容。

利用 getVal() 去簡化程式碼是一個蠻常見的程式技巧,但如果你再拉高一個層級去看的話,這應該是對某個 <form> 底下所有的 input 內容打包成 data 的操作。其實這在瀏覽器的 Web API FormData() 就已經有提供這個功能了,所以你不太需要自己再手刻一個包裝功能。

FormData() 的使用範例 (引用前面提到的連結) 如下:

<form id="form">
  <input type="text" name="text1" value="foo" />
  <input type="text" name="text2" value="bar" />
  <input type="text" name="text2" value="baz" />
  <input type="checkbox" name="check" checked disabled />
  <button name="intent" value="save">Save</button>
  <button name="intent" value="saveAsCopy">Save As Copy</button>
</form>

<output id="output"></output>
const form = document.getElementById("form");
const submitter = document.querySelector("button[value=save]");
const formData = new FormData(form, submitter);

const output = document.getElementById("output");

for (const [key, value] of formData) {
  output.textContent += `${key}: ${value}\n`;
}

另外要提的一件事情是那個 content 和 pwd, type, code, subbsn, title, sign, ptype, bbsign, ccsign 這些變數都不是透過 selfPush() 的參數傳入的,這其實不是很好的程式風格。其實 jQuery 或是 document.getElementsByXXX 的程式碼都有類似的問題,所以後面才會透過元件化的方式去管理越來越複雜的網頁結構,基本上 vue, react 這些前端框架都有元件化的思維了。

大概是這樣,以上

這是一個腳本 html的話是在一個論壇上執行的 程式碼大概幾千行
如果不貼html就等於要通靈 那我想是你自己的問題
其他人很明顯都理解了 甚至看出這段代碼的意義
感謝您的解答 我學到了很多 如有冒犯還請見諒(・ω・)

我要發表回答

立即登入回答