日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

工程设计论——如何写好工程代码

發布時間:2024/8/23 编程问答 57 豆豆
生活随笔 收集整理的這篇文章主要介紹了 工程设计论——如何写好工程代码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

簡介:設計是在對需求的認知不完整的情況下,對被設計對象進行求解的一個過程。這就迫使我們需要一邊認識被設計對象,一邊進行求解。為了并行化地進行這一過程,也為了使得對被設計對象地認識有初步的研究工具和基礎,我們總結出了一套利用分拆提供弱約束,并基于這種分拆,來并行進行不同組件之間的設計的流程。

作者 | 任增
來源 | 阿里技術公眾號

一 內容概述

  • 從抽象的工程設計論角度闡述了如何寫好一份代碼。闡述了設計模式和設計原則的底層原理。
  • 解釋了設計模式與設計原則適用的場景及局限性。工程設計論是在有限設計能力下對被設計對象進行的認知和進行逆運算的過程。在不符合這一條件的領域,不應當死扣設計模式與設計原則。在軟件領域,一個顯而易見的例子就是不要在極度追求性能的代碼中死扣設計模式與設計原則。
  • 解釋了設計原則中的單一職責原則為何難以掌握和運用。
  • 面向接口設計是軟件系統設計的最終形態,對開發流程中先寫單例再開發的原因做了解釋。
  • 二 理論基礎

  • 哲學基礎:羅素《哲學問題》。
  • 數學基礎:矩陣理論,工程控制論。
  • 工程基礎:一定工程設計經驗,如代碼開發等。
  • 設計科學基礎:謝友柏老師的《設計科學與設計競爭力》,Nam Suh的《公理設計》。
  • 三 什么是設計——設計和計算與認知之間的聯系

    一門科學的建立,應當首先明確本學科的局限性,確定本學科最基本的問題與框架。明確的基本框架應能夠迅速得到一門學科的基礎結論與研究方法;明確的基本問題可以用于檢驗上述的結論與方法。指出自然界中每一杯水中都有金元素并不能對金礦的發現起到什么促進作用。設計科學的現在的發展應該做減法而不是做加法。對于設計所具備的特征,有很多描述。這些描述最基本的共同點是設計是需要達到一定的目標的(即需求)。其他特征并不是設計最基本的特征。例如最優化設計中就沒有需求變更,logo設計中就沒有系統故障。

    如果認同需求是設計的共同點,那么搞清楚需求是什么則是重要的。 大部分人都認為,在我們的實際工作中,需求是不明確的,不完整的。那我們不妨用辯證的思維來考慮這個問題的反面,什么是明確的,完整的需求?一份完整的需求,對于所有人而言都是清晰的,不會產生什么不一樣的理解。那么對于什么樣的產品能夠滿足相應的需求,也應該是清晰的。用集合論的話來說,一個集合被其外延所完全確定。換句話說,如果需求能夠被一個確定的驗收方式來定義,比如說單元測試,那么這份需求可以說是明確和完整的。

    我們還需要更進一步地探討什么是驗收。以單元測試為例,我們用單元測試來輸出一個True或是輸出一個False;如果認為單元測試本身是一個函數,那驗收就是要求被設計對象在該函數下的相必須為True。那么,如果我們的需求足夠簡單,會發生什么情況?比如說我們的需求是找到一個x,使其滿足x+1=0,我們一般稱這種問題為求解,或者是逆運算。可以看到,當我們對需求及其實現方式的認識完全清晰的時候,需求將退化成為一個函數,設計將退化成為逆運算的過程。

    設計的過程中,我們對于需求及實現方式的認識是不全面的,這是其與逆運算不同的核心點(而不是需求不明確或者是需求會發生變更)。例如化工產品的合成路線設計,例如高效排序算法的設計,都不存在需求本身不明確的問題。認知的不全面迫使我們需要在設計的過程中,一邊對需求及其實現方式進行認知,獲取更多的知識,一邊進行求逆運算,找到能夠滿足需求的實現方式。

    四 工程設計的過程

    在進行工程設計的過程中,對于認知和計算的交替流程,我們總結了一套行之有效的經驗,即對需求的拆分和組合。

    我們剛剛已經說過,需求本質上是要求一個對象,在某個函數下的像具備某些特征,這本質上是一種約束。而“被設計對象由A,B兩個組件構成,A具備123特征,B具備456特征”,這和需求的描述方式沒有什么不同,本質上也是一種約束。也就是說,分拆本身也是對被設計對象的一種約束,只不過滿足分拆約束的對象并不一定滿足需求的約束。因此我們不妨把分拆的約束當作一種對被設計對象的弱約束。

    因而工程設計可以被總結成為如下的流程:

  • 根據對需求的相關研究,給出實現方式的弱約束,我們一般采用對系統拆分的方式來進行弱約束。在軟件領域,最常見的弱約束就是對組件劃分的約束,各個部件之間的依賴關系,接口的定義,數據交互方式之間的約束。(認知過程,我們一般稱之為需求拆解與架構設計)
  • 利用第一步的弱約束,來對需求中的強約束的實現方式進行具體的分析和求解。(逆運算過程,我們一般稱之為編碼)
  • 我們剛剛已經說明了,分拆本質上也是一種約束。第二步中的求解結果,仍舊有可能是一種對子系統需求,此時就需要我們繼續進行更加細化的設計。

    引入弱約束這個概念,是因為在我們對被設計對象一無所知的情況下,研究如何實現相應的需求是相對困難的。那么我們不妨假設被設計對象具備某些性質(這種假設往往也強依賴于個人經驗),并將這些假設性質(比如說接口)作為研究如何實現的一種工具和框架。

    例如在代碼設計中,拆分為A,B兩個模塊并進行并行設計時,如果在A模塊的實現流程完全不知道B模塊的信息,那么將會對A模塊的設計產生巨大的阻礙(比如前端完全不知道后端的數據格式)。但是,B模塊的具體實現方式還未確定,此時A模塊也不可能對B模塊的信息由完整的了解,且并不是每一個B模塊的信息對于其他模塊都是有用的(比如后端選用的數據庫格式,后端部署的位置,后端的實現方式)。所以我們需要折中的對B模塊進行約束(比如規定接口),使得A模塊能夠獲得必要的相關信息。了解過認知論的同學也應該知道,這種接口本身就是一種對B模塊的認知(參照羅素的感覺材料或是我在前序文章中所述的“關系”)。我認為這是依賴注入的底層邏輯,也是面向接口設計將成為軟件設計的最終形態的底層依據。

    在這個例子中,工程設計與科學研究后進行計算的最大區別即在于,第二步中的具體實現過程是并行的。各個組件的實現的并行在軟件工程中是常見的(前后端分別編碼,最后進行調試即是如此)。我們當然可以在完全研究清楚J(X)的性質下,再去進行設計。限制我們不去這么做的條件,并非是這樣得到的產品效果一定不好,而是設計需要投入的工期與人力有限制。完全設計好前端之后,再去進行后端設計,當然是可以的,但是這種串行化的工作模式,顯而易見的會對工期造成負面影響。

    為了使得這種拆分方式可行,獨立職責的原則就需要被引進以保證最后的組裝工作順利完成。在上一步中,我們的工作是并行的,意味著我們并不知道f(X),g(X),m(X)所需要取得的值是多少。如果我們最終研究得到

    那我們顯然是找不到相應的解的。這就需要我們保證f({X}),g({X}),m({X})之間的相互獨立。我們對拆分地獨立性及其負面影響進行進一步地探討:

    這一規則對應于軟件領域中的單一職責原則,有人評論這一原則是較為難以運用和掌握的(“單一職責原則是最簡單但又最難運用的原則”)。事實確實如此,接下來我們將對這一點進行探討。

    我們換一種看起來正確的模棱兩可的表述更方便我們發現問題在哪。這個陳述是:獨立的功能應當由獨立的類來實現。那么,問題出現了。我們怎么去判斷兩個功能之間相互獨立?熟悉哲學,并對哲學中對“Free”的討論有接觸的人會很快反應過來,“Free”這個詞必然是建立于某種映射之上,單獨說A與B“Free”沒有任何意義。家庭教育和學校教育是否獨立?道德教育和智力教育是否獨立?從不同的角度會有不一樣的答案。從時間上,家庭教育和學校教育相互獨立;從評分標準上,道德教育和智力教育也相互獨立。如果把教育也作為一種設計,我們是應該把教育劃分成為家庭教育和學校教育,還是劃分成為道德教育和智力教育?劃分的依據究竟應該是什么?

    顯而易見的事情是,我們所能夠接受的判斷功能之間的相互獨立的依據,應該是從其實現方式上相互獨立。那么上面那句話,就可以改寫成為:實現上獨立的功能應當被獨立地實現。這有點像一句政治正確的廢話,其具體的運用強依賴于設計人員對于相關領域的事前經驗與判斷。不具備相關領域的經驗,進行功能劃分必然會出現一些搞笑的結果。這就是單一職責原則是最簡單,也最困難的原則的原因。

    五 總結與局限

    設計是在對需求的認知不完整的情況下,對被設計對象進行求解的一個過程。這就迫使我們需要一邊認識被設計對象,一邊進行求解。為了并行化地進行這一過程,也為了使得對被設計對象地認識有初步的研究工具和基礎,我們總結出了一套利用分拆提供弱約束,并基于這種分拆,來并行進行不同組件之間的設計的流程。由于分拆只能提供關于被設計對象的較弱認識,因此依賴倒置和面向接口設計是必須的。為了使得并行化的設計最終可以被組裝,單一職責原則(獨立原則)是必須的。

    可以看到,整個設計理論是必須基于對需求的認知不完整,且需要低成本(首要的是時間成本)地完成設計這一條件。對于設計周期比較長,認知較為充分的領域,設計理論并不適用。完全只用設計模式來衡量設計的好壞,也是不可取的。這方面的反例有很多,LeetCode上面的題目,恐怕沒有哪一個符合了設計模式,比如說找鏈表倒數第k個節點中的雙指針就是一個典型。對于人體而言,也并不遵循什么單一職責原則,甚至可以說耦合地不像,人在饑餓的時候,可以分解蛋白質來供能;我們在飛機設計過程中,有考慮過在液壓油泄露時,拿燃油來充當液壓油么?一些經典設計也并不遵循設計理論與原則,例如活塞環既能夠防止漏氣,又能夠降低摩擦磨損,這顯然也不是符合獨立公理的。

    只有對設計科學的底層邏輯有著深入的研究,才能使得這門科學發揮其真正的作用。雖然本文盡可能地對這個領域進行了一些減法地操作,略去了一些不核心的要素,但是無論在理論上,還是例子上,都沒有能夠提供一個真正能夠被驗證成為正確或是錯誤的想法或是命題。本文甚至連錯誤都算不上,這無論如何都是讓人不滿意的。

    六 附——利用分拆來設計系統的一個例子

    很多設計領域的文章提出的例子,都是一些已有的設計;或是拿著根本沒有市場的需求來設計一款產品。這種先射箭后畫靶的行為并不能促進科學的發展。因此找一個大家都熟知的領域,提出解決起來較為有難度,但是需求明確的問題來作為探討的例子。很幸運的是,我的確解決了我自己提出的問題。

    在機械領域,平面桿件機構的設計是最基本的問題。例如對下圖中這種四桿機構,我們經常會進行擺角的設計等工作。那么,我們能不用勻速的電機和平面桿件,使得平面桿件上的某一點有著指定的軌跡?例如用平面桿件畫一只兔子?

    對于這個問題,我們梳理我們已經知道的知識,來給出一些弱約束:

    那么,我們再由拆分給出另外的弱約束,以解決這一問題:

    在這樣一個弱約束下,我們的問題就變為了:

    如何通過一些圓周運動,及建立在其上的加法體系,擬合任意一個周期運動。

  • 如何找到一個連接組,使得其具備上述條件。
  • 問題一的答案由傅里葉變換給出:
  • 問題二可以由如下桿組完成,轉動副2始終為轉動副1,3的中點:

    最終的設計,我用了16個主動件,及16個連接組,共計80個桿件,得到的結果已經在上圖中展示了。

    誠實而言,我認為這個例子在說明弱約束和強約束,以及拆分對于工程設計的必要性方面,仍舊難以擺脫先射箭后畫靶的嫌疑。但是至少,我不認為我設計的機構,就是本問題的最優解;我想本問題用以說明工程設計并不能得到最好的設計這一點,還是足夠的。

    原文鏈接

    本文為阿里云原創內容,未經允許不得轉載。?

    總結

    以上是生活随笔為你收集整理的工程设计论——如何写好工程代码的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。