程序員如何避免寫過多的業務邏輯代碼?

最近產品那邊需求堆得很厲害,大部分時間都花在了業務邏輯的實現上了,感覺很難從中學到更多新東西,反而總是重複比較機械化的工作。不知道各位前輩在這樣的情況下會怎麼做?


出自 是不是服務端編程剛開始都得從寫業務開始?

如果忽略技巧,用蠻力寫業務邏輯,不追求代碼之神,敲完就算,當然無聊啦。

---

你可以

switch (gender):
case "male":
if (level === "gold") {

} else if (level === "silver") {

} else {

}
break;
case "female":
if (level === "gold") {

} else if (level === "silver") {

} else {

}
break;
case "unknown":
if (level === "gold") {

} else if (level === "silver") {

} else {

}
break;

這是一般業務邏輯程序員認為的「業務邏輯」,你每天寫這種代碼,當然覺得無聊。

你也可以

GENDER = {
MALE: "male",
FEMALE: "female』,
UNKNOWN: "unknown"
}
LEVEL = {
GOLD: "gold",
SILVER: "silver",
BRONZE: "bronze"
}

avatars = {
GENDER.MALE =&> {
LEVEL.GOLD =&>
LEVEL.SILVER =&>
LEVEL.BRONZE =&>
},
GENDER.FEMALE =&> {
LEVEL.GOLD =&>
LEVEL.SILVER =&>
LEVEL.BRONZE =&>
},
GENDER.UNKNOWN =&> {
LEVEL.GOLD =&>
LEVEL.SILVER =&>
LEVEL.BRONZE =&>
}
}

user.gender = (user.gender in GENDER) ? user.gender : GENDER.UNKNOWN
user.level = (user.level in LEVEL) ? user.level : LEVEL.BRONZE

user.avatar = avatars[user.gender][user.level];

這樣寫業務邏輯就有趣多了。

後一種是Data Driven的思考方式,用數據,或者設計數據來驅動邏輯,讓邏輯的外觀從代碼里消失,從而讓代碼更緊湊,節奏感更強,讀起來更舒服,改起來更方便。這是在web開發里常用的技巧,遊戲邏輯里應該也有不少數據驅動的場景,如果你能為特定邏輯設計出一目了然的數據,就能大大降低邏輯的複雜度,寫出的東西更魯棒,效率通常也更高,就不會覺得寫這種業務無聊了,因為有技巧在裡面。

---

你可以

for (items) {
item[..] =
// or
if () {
return item
}
}

也可以

items.each(item =&> process(item))
items.filter(item =&> verify(item))
items.map(item =&> update(item))

用好函數式,能幫你化解各種無聊的循環,外觀上看,代碼的抽象層次更高了,語句更清晰了,讀起來更舒服了。

---

你可以

class {
showLogo () {
showAd()
...
}
showBanner () {
showAd()
...
}
showSidebar () {
showAd()
...
}
}

也可以

class {
@decorated by AdDecorator
showLogo,
showBanner,
showSidebar
...
}

簡單的Decorator,是不是讓代碼緊湊精簡,有意思多了?

---

你可以

s : string = "thanks "
if () {
s = s + name
s = s + " for purchasing
if () {
s = s + quantity
s = s + product
}
}
s = s + ..

也可以

t = "thanks {name} for purchasing {quantity} {product} .."
s = t.compile({name, quantity, product})

把比較髒的局部拼接邏輯變成一目了然的模版,品味高出截。

---

你可以

function attach() {
app.A =
db.update(app.states)
log(..)
}
function move() {
app.B =
db.update(app.stats)
log(..)
}

也可以

app.on("change", "stats", stats =&> {
db.update(stats)
log(..)
})
function attack() {
app.update(A ..)
}
function move() {
app.update(B ..)
}

...

同樣繁雜的業務邏輯可以寫得拖沓重複,無聊透頂,也可以寫得精粹漂亮,有樂趣和美感啊。只需要在敲鍵盤前多花點時間來構思,並不難。

你確定底層編程需要更高階的思想嗎,其實只是數據和操作的形態不同罷了,思維和技巧還是適用的。再說要多底層才能滿足你的虛榮心呢?

* 以上代碼為偽代碼,概念實現請參照編程語言。
* 支持你自己 https://www.linkev.com/?a_aid=itlr
* vultr.com 有目前性價比最高的 $5 VPS,768的內存


比起寫業務代碼更不幸的是,主要工作是修 Bug,bug,buG, bUg。

在一家大的公司里,不同的人總會有不同的運氣:

  • 運氣好的人遇上一個好的項目,升職加薪,從此就走上了人生的巔峰。
  • 運氣差的人攤上一個差的項目,升不了職,少加了薪,並且還獲得不了技術成長。

我剛畢業那會兒,所在團隊的主要工作是,維護一個『又老又舊』的系統。比起寫業務代碼更不幸的是,我們的主要工作是修 Bug,bug,buG, bUg。

那一年多里,儘管都是維護舊系統和少量的新需求,我們還是在飛速的成長~~。而來源主要是:

  • 組內技術活動
  • 花時間投入練習
  • 假想項目的重構

當你在有限的條件下,還能做出一定的成績,到底還是相當有成就感的。

只修 Bug 是怎樣的一種體驗

在這樣的項目里:

  • 工作一個月時,你打開 Backlog,看看需求卡,發現那張需要三個人天的卡,好像會更有挑戰一些。
  • 工作兩個月時:你打開 Backlog,看看需求卡,發現完成這卡只是時間問題。
  • 工作三個月時:你打開 Backlog,看看需求卡,發現清清楚楚地知道修改哪一行。

有一天,業務人員來了一個新的需求。雖然只是加上一個新的導航,但是你總會小開心一會兒。

可你來到這樣的項目時,你總會想著離開,向自己的 Buddy、PM 、Sponsor 訴說。可惜,你只是一個畢業生,太年輕了。對於你來說有挑戰性的項目,不會考慮要你的。在你的感覺里,那種『自己是大公司的輪子』的感覺就特彆強烈。多你一個不多,少你一個不少。你走了也不會影響這個項目,畢竟招一個人來修 bug,還是蠻輕鬆的。因此,這個項目走了一個又一個技術好的人,卻也來不了一個 senior 的人。

時間一久,每個人都充滿了危機感。我們總是擔心:當你換到另外一個項目的時候,別的項目 PM 會考慮你么——因為你是來自這個沒有挑戰性的項目。這個時候,你已經無路可走了,你必須去提高你自己

當別人救不了你的時候,你只能自救。當別人救不了你們的時候,你們也只能自救。幸運的是,我們當時還有足夠的時間,可以提高項目組的水平。於是,我們對組織了各種的組內技術分享、workshop、培訓等等

當你有強烈的改變意識的時候,那麼事件就會變得很簡單。真正可怕的是溫水煮青蛙式的,而當你面對的是溫水,你總會不斷嘗試去離開。

組內技術活動

當你們項目無聊的時候,總會空餘一些時間。上進一點,就會創造一些學習的條件。有了條件,那麼剩下的就是靠人為了。

於是乎,我們在每周挑取了兩個時間,做一些技術的事情。包含了下面的一些內容:

  • 技術分享。
  • workshop。
  • kata。

不同的活動都有不同的目的,有的可以提高演講者的技術能力,有的則是可以一起提升能力。下面就讓我們詳細了解一下不同的活動。

技術分享

想必大家都已經知道這個是什麼了~~。當時的情況,大概是我們七個人里,每周會有兩次技術分享。分享的主題會比較廣泛:

你最近在玩的技術棧。當你們所用的項目技術棧,比較老舊的時候,就想不斷地去嘗試新的技術。在工作之外,便會去玩一些『新鮮』的技術棧(坑)。它就像是一股清流,即使不能幫你清除舊的污水,也能讓人們看到一絲希望。而且除了能提升團隊的視野,還可以將之視為替換現有架構的探索。

項目相關的技術及業務。在沒有結對編程的項目里,共享知識對於團隊來說是一個頭疼的問題,而技術分享就是最簡單的方式。不過,對於新人來說,讓他們做相關的技術分享才是最好的方式。這也視作為我們對新人的考察:

  • 對於項目的了解程度
  • 找到缺少的相關知識
  • 培養新人的表達能力

在項目上,這幾乎是每個新人都會經歷的一個分享~~。

特定主題的技術分享。即,我們限定好一個大的主題,每個人挑選一個特定的主題來分享,它可以人為地提高整個組在某一領域的水平。當時我們做過 SOLID、設計模式、前端相關等特定主題的分享——每個人挑選設計模式中的一個模式,然後做相關的技術分享。當你做分享的時候,你對這模式就比較了解;而別人做分享的時候,也能引發你的思考。由於這些主題之間的相關性比較強,它可以加深對這一領域的印象。

其他雜七雜八的內容。過多的技術分享,可能會導致大家精疲力盡,因此就會有一些技術之外的分享。比如,你喜歡的各種動漫啊、知乎上流行的程序員女裝啊等等。

而就效果來說,技術分享對於分享者的能力提升比較大,聽眾則是知道有這個東西,啟發性一般都會比較少。如果是針對於提升能力來說,應該採用 workshop 等方式。

workshop

當項目上要採用一個新的技術棧時,僅僅中是一個技術分享是不能解決問題的,你還需要有 workshop 這樣的東西。比如你們將在新的項目里引入 Next.js,那麼這個時候就需要有一個 Next.js Workshop。由組織者來規劃每一步的內容,第一步做什麼,第二步做什麼,等等。參與者則是單獨或者結對的形式,按照組織者的步驟一步步往下來做相關的技術練習。比如在 workshop 開始前,先 clone 並搭建好基礎代碼(hello, world)。開始的時候,便是先實現一個簡單的 header,然後是添加樣式等等。

也因此在這樣的 workshop 里,我們不僅可以聽過相關技術棧的知識,也能掌握一些相關技術棧的具體實踐。

kata

一種編程練習方式,針對某個題目反覆進行操練,達到熟能生巧的目的。簡單的來說,就是你一直練習某一個特別的東西,直到你習慣了。比如,對於 TDD(測試驅動開發,先寫測試,並由測試驅動出功能) 的練習。

在平時工作的時候,我們不會總是習慣於 TDD 的流程:測試 -&> 實現 -&> 重構。特別是,當你的卡就要被打包到新的 Release 包時,先實現總是會保證交付的。又或者是,當你對代碼庫特別熟悉的時候,你可能兩三分鐘就改完代碼,然後去喝咖啡,再回來花個十幾分鐘寫一個測試。而當你不熟悉 TDD 的時候,你更不會採用這種方式,你會的可能就是 Test First。為了將 TDD 的思維融入你的想法里, 你就需要大量的這種練習~~。

在這個時候,我們就需要嚴格的按照步驟,一步步往下執行。以便於在將來,我們可以嚴格的按照這些步驟來執行。

除此,還有一種方式可以做,只是我們沒有在這個項目里實施。

dojo

dojo,(日語:道場)。在西方世界,dōjō 一詞主要指的是一個專門針對日本武術的訓練場所。在敏捷團隊里,Dojo 的進行方式比較『詭異』,也比較有意思。

如果你了解過結對編程的話,可能就會對兩個人的結對過程比較感興趣。按我的理解,結對編程存在著三種不同的階段:teaching(引入門),driver-navigator(有經驗與新手),結對(有經驗與有經驗)。即在實現功能的時候,兩個人會輪流寫測試和實現功能——你先寫測試,我實現功能,然後換角色。而 Dojo 就是一堆人在輪流寫代碼:

即在有限的時間裡,每個人上去實現同一功能的代碼。

如,A 實現了測試,B 上去實現業務,C 上來重構。D 上來看了看,你們寫的代碼都是 xx,於是 Revert 之前寫的代碼。可惜 D 的時間也只有七分鐘,所以 E 上來 Revert Revert。。。

笑~~

花時間投入練習

限於之前已經有相當多的文章,介紹練習相關的技巧,如:

  • 《GitHub連擊500天:讓理想的編程成為習慣》
  • 《關於編程,你的練習是不是有效的?》
  • 《我的成長四步曲》
  • 《我並不聰明,只是多練習和思考》

這裡就先略過去了~~,有興趣的讀者可以閱讀上面的內容。

假想項目的重構

哈哈,如果你覺得你的項目技術棧老舊,那麼你一定在腦子裡使用了 N 種技術棧,對他們進行重構了。並且當你有一些時間可以分配到上面,如下班前的一個小時時間,又或者黑客馬拉松等等。那麼,你一定會開始去做這樣的事。

與上面的技術活動相比,這是一個對於業務(我的意思是,對於公司來說)更有價值,並且更容易說服別人的方式。

  1. 學習別的項目的技術棧,然後將之應用到現有的系統上。
  2. 使用一個新的技術棧練習, 以此作為技術支撐,在未來替換現有的系統。

由於我們與其他項目大組的業務是相似的,並且他們的團隊規模差不多是我們的 10 倍。當某個新的應用完成後,我們要做的便是:fork from xx,將改吧改吧,應用到我們現有的模式上。

這個時候就有問題了,一般這些新的項目都會採用最新的技術棧。在正式引入項目之前,我們都是要學習這些技能,並配合業務做一些修改。也因此,我習慣性的將這種項目視為修改 bug、bUg、Bug。

後來,我們突然有機會彎道超車了,我們可以先重構某一部分系統。『因為已經做好相關的技術積累,並沒有遇上一些太大的問題』。只是我們實施一半的時候,就發生了一些意外~~。後來的後來,這個項目「到期結束」了~~

現在是 2017 年,當你的項目還在使用舊的 jQuery + Backbone,又或者是 Angular 1.x。並且你們覺得他們有一些問題,這些問題採用一些新的框架,如 Angular 2,又或者是 React 能解決這個問題的話。這個時候,我們就可以嘗試去學習新的技術棧,並驗證它的可行性。當有一天,你們需要去重構現有系統的時候,你拿出的直接是一個可行性的 Demo,而不僅僅是一個理論上的東西。

當時我們的項目想替換掉舊的搜索引擎,我們先是用 Solr 實現了一遍 DEMO,又用 ElasticSearch 做了一遍 DEMO。同時,我們也在計劃替換應用部分的功能,我們先用 React 實現了一遍 DEMO,又嘗試用生態純靜態的方式玩了一遍。。。生命可貴,可以多玩就多玩一些吧。

小結

所以,你是因為加班呢,還是因為加班,才沒有時間學習???


不寫業務代碼?你寫什麼?又來高中程序愛好者三板斧,一言不合寫操作系統,一言不合看linux源碼,一言不合實現編譯器?

大廚做切配就要做一年,你做個程序員連業務代碼也不寫?

我就直說了,都是好高騖遠。

不服?我寫了5年+業務代碼,要不要我們比比技術?


與你的期望相反。

程序員多寫一些業務代碼沒什麼壞處,反而會提升自己的技術水準。

關鍵點在哪裡?

就是怎麼避免重複的勞動?

1。你可以抽象出公共的代碼,以組件和定製化的形式去復用。

2。你可以手寫代碼生成,以半自動的方式去生成代碼。

凡是牽涉到重複勞動的地方,都是展現出你自己價值的地方。

這也是程序員改變世界的動力。

很多東西,都是因為大家覺得太繁瑣了,所以開始寫一些小工具來提升效率。

你現在已經有這種機會了,只是要不要繼續走下去而已。


用可視化的方式維護業務邏輯,具體來說就是:

通過ORM維護業務對象
通過規則維護業務對象上的邏輯
通過流程來組合規則
通過介面來概括流程

這四步是從最後端一步一步往前做,每一步都可以可視化。

然後看前端,以往很多方案都只考慮定製界面,這裡面要的是把展示層做一些封裝,但跟後端的結合一般都不理想,現在有基於MVVM的框架,可以再做一層這裡面M,甚至VM一級的定製,然後通過M跟上面搞出來的後端介面做一次關聯,然後把定製出來的界面跟VM做綁定就可以了。

總之,減少機械工作的重點就是自動化,可視化,然後把多數事情交給業務專家,而程序員只負責維護這套機制本身。


很多說到可視化,這個開發完之後全部讓別人操作自然是極好的,但是極度複雜的業務邏輯下,有多少人能學會用這個呢?到頭來搞不好還是開發者自己來維護....這個時候可視化的效率以及可維護性就遠遠不及配置文件了。

其實最好的方式還是要做好需求分析,讓系統更加好的與現實業務融合,這個融合不光光系統的變化,還有業務本事也要進化。

再說說題主關於進步的困惑,做信息系統開發的,對於業務的了解是非常非常的必要的,這就是財富。在從技術角度來講,每次改動都應該審視一下自己編碼上的問題,以及自己在功能設計上的問題,讓更多的東西變成可配置的。可以抽象的業務盡量去抽象。如何重構效率是最高的?這些都是值得思考的。

最後說說,那麼多開發人員都希望自己是做核心工作的,覺得重複枯燥的工作都是沒有價值的——是的,是沒有價值的。所以,換工作或者換行業吧。


面對重複、機械化的工作,程序員天性使然會無所不用其極地把那些工作自動化,或製作工具讓工作交給其他人解決。

以遊戲來說,需求經常增減,或要調整,最好可以盡量用工具去修改,而不用改程序。簡單的是填表,複雜的可能是樹狀甚至是圖形式的邏輯編輯器。


工作有成績的人才有選擇工作內容和職位的機會,所以先把業務代碼寫好吧


多寫,寫到某一天你受不了變幻莫測的需求、浩如煙海的bug和無休止的加班時。
然後你可能會想想找條出路。
或是換個公司,或是開始學習有針對性的技術。多半兩者都做。
多數碼農就是這樣反覆磨礪的過程吧。


新東西?在公司內做開發跟你自己搞開源不一樣,新的東西很多時候沒有經過穩定性的沉澱,企業不想冒太大的風險。企業是商業化的,很多程序員卻只是站在純技術的角度看待問題。你需要的是想辦法儘快把活解決掉,去研究你所謂的「新東西」,「有技術含量的東西」。不然去了哪個公司都一樣。

程序員平常加班嚴重,是怎樣兼顧自己個人能力提升的? - 知乎用戶的回答


你在公司不寫這個,你要寫啥?

公司雇你就是干這個的啊


一、學會寫自己的代碼生成器。
二、學習優秀的設計範式。
三、跳槽。


擼個簡單一點的DSL教給產品狗,然後就可以讓他們幫忙寫邏輯了。
金融行業和遊戲行業里很常見。


讓產品學會並喜歡上寫代碼。


設計模式(策略模式會用的多一些?);
IOC;
工作流等配置化思路;


其實不要指望一業務公司的項目,會對你的技術有提高。
首先提出需求的人就是外行,因此外行是只看結果不看過程,外行是不會管你代碼里用了啥牛X的技術,只要你做出來了能用即可。
所以說有些程序員學完之後,總想實際公司業務做點什麼提高自己的技術,這種想法就不現實。
提高技術要自己去找項目發覺需求,等你主動出擊時更是提升自己的時候,到那時你會發現,你可以不需要產品經理或客戶這種挖掘需求的人了,因為對於需求挖掘你已經比他們有經驗了。
同時自己的技術也提升到一定水平了。


以我的經驗,程序員被「過多的業務邏輯代碼」搞煩,大多不是技術問題,而是管理問題。

對於面向業務的產品,很多邏輯都是和計算機世界的「規則」沒什麼關係的,而是和現實世界中其他領域的「規則」有關係,比如財務制度、和商業合作夥伴的結算規則、法律規則,當然,還有產品經理腦子裡想出來的各種驚世駭俗的創意,這些玩意都是和計算機世界沒啥關係的,用計算機世界的東西去滿足這些要求,程序員當然覺得不算「技術活」,做多了當然覺得累。

其實,對於以盈利為目的的公司,不是學校,不可能讓程序員只是研究「純技術」的東西,所以總要有人去處理這些業務邏輯代碼,這是躲不了的,你不幹也有別人要干,你不在這個公司干去了別的公司也要干。認識到這一點,容易想通一點。

回到第一段,我說了,這往往不是技術問題,而是管理問題。

公司是業務支撐的,不是靠技術支撐的,所以其實了解業務規則非常重要,如果你將來想要創立一個自己的公司,那就應該多了解這些技術之外的規則,即使你只想做技術人員,了解這些規則也對你沒有壞處,至少你知道衣食父母都是怎麼想的。主要的問題,是這些業務規則往往傳達到程序員頭上是,沒有解釋「為什麼」,只是生硬的需求,而且即使有為什麼,以非計算機專業人的手法,往往也是比較粗糙的。我不是瞧不起非計算機專業的人士,但是真的大部分需求來的時候在程序員眼裡都是模糊而且缺乏邏輯的,不反覆討論好幾回是扯不清的,這也是讓程序員反感的原因之一。

至於怎麼解決這個問題,我覺得只能從管理入手,以下為科幻時間,我知道大都是無法實現的:-)

1. 和各部門溝通協調,確定業務需求的指定原則,產品設計要有固定的原則,才不會今天一套明天一套。

2. 控制業務邏輯的變更頻率,對於頻繁修改業務需求的部門,降低信用值,延遲對他們的響應。

3. 輪班制,讓程序員輪流處理業務邏輯和「技術代碼」。

我相信在一個講管理尊重人的公司,一定會解決好這個問題的。


公司是需要出產品的,不是讓你來研究這研究那的.產品靠什麼出?需求更新,產品迭代,活動上線等等.這些說白了,全是業務.那麼技術相關的東西該怎麼提升呢? 這就需要你所處的位置和接觸的人了,假設,你是看著這個項目從一個量級走到另一個量級,那麼很好,你可以學到許多東西.如果公司產品一直不溫不火,沒頭沒尾的更新.那麼,該換公司了.


從老闆的角度看,花錢雇你來工作的,不是雇你來學習的,你的價值不在於有多少技術而在於能不能解決問題。
想學新技術,放到業餘,自己擠時間;或者努力把業務邏輯寫好,往上爬到管理層,任務都由你分配,這是就可以安排時間半脫產研究技術了。


我很奇怪,
我們做軟體的目的不就是解決業務問題嗎?
不寫業務邏輯代碼要程序員做甚?
你要覺得重複,機械,那就動腦子,如何架構,如何抽象,怎樣復用。唯有用腦子編程序,才能提升成就感,減少體力活。


推薦閱讀:

如何看待11年的熱帖《我在趕集網的兩個月》的北郵生?
如何理解喬布斯說的「消費者並不知道自己需要什麼,直到我們拿出自己的產品,他們就發現,這是我要的東西」?
歷史上有哪些「大力出悲劇」的產品?
App 產品原型設計用什麼軟體?
智能硬體產品經理需要哪些技術基礎?

TAG:產品 | 程序員 | 職業發展 | 成長 |