phper:敢問路在何方

很多php程序員存在未來發展方面的困擾,介於各方面的因素,phper 比其他程序員更容易遇到上升天花板。

一方面,一般只有初創企業爲了快速實現產品上市以及極容易招到 phper 才使用 php 來實現公司的全部業務,大廠的核心業務都不是 php 做的(阿里用 java,騰訊用 c++),php在大廠只能做邊緣功能如管理後臺。

另一方面,相比於 javascript 在前端領域的一枝獨秀,各種玩出花,php 在後端雖然市場份額可觀,但有 java、go、python 甚至是 node 的強力挑戰。

最大的問題其實在於,由於把 php 作爲核心編程語言的基本都是中小公司,而這些公司的業務體量根本和大廠不是一個量級,並不需要面對高併發、高可用什麼的高級架構設計,結果就是大部分 phper 終其一生都是在做着毫無挑戰的代碼堆砌工作,技術上並無多大成長。

php 程序員很少涉及底層,甚至很少涉及宏觀。phper 缺少平臺。

(在面試過程中,我發現 phper 面臨的一個尷尬局面:他們所在的公司,最終要麼倒閉,要麼轉了 java,php 只是作爲“快速原型”時期的工具而已)

現實中很多程序員意識到這點,想要轉型,於是通過業餘時間學習諸如 go、python 等第二語言。有轉型成功的,但大部分都失敗了。

也有人想轉架構,於是去學 k8s、docker、分佈式架構、“三高”架構等,但相對於前者,這種成功率更低——因爲根本就沒有實踐的機會,終究是紙上談兵,一知半解(很多人僅僅是會使用而已)。

於是,很多人 35 歲前在各種創業公司碼代碼(很多人是碼一家倒一家),35 歲後成了水果販子。

然而,在我看來,phper 並非完全沒有出路,而且和其他主流語言一樣,出路是一樣的,雖然可能相對來說走得要更辛苦些。

每個 phper 要想擺脫平庸,首先要構建自己的技能樹。

那麼,phper 技能樹中最重要的是哪些?分佈式?容器編排?微服務?serverless?

都不是。在我的排位中,這些看着高大上的東西一個都排不上前十,在你還沒有真的達到架構師的水平之前,我的建議是一個都不用研究。

c 語言

網上廣爲流傳的標語是類似“我用 3 行 python 就能實現的東西,爲啥要用 300 行 c 去實現?”

這好比問阿里:市面上有那麼多消息隊列中間件可以直接用,你爲啥要花費人力再去搞個 rocketMQ?

我們說不要重複造輪子,但實際情況是我們(特別是大廠)天天在造輪子(谷歌三天兩頭就搞個什麼語言出來),目的是增加自己的技術儲備。

c 語言是程序員界的通行證,是一個程序員(特別是 php 程序員)段位高低的重要標誌,也是 phper 突破瓶頸的最直接有效的手段。

c 語言是 phper 最重要的第二語言。

爲啥?正是因爲 c 語言是底層語言,直接面對計算機(內存)。因爲 php 太過方便,屏蔽了大量底層細節,這對公司、對工程是好事,對程序員的成長卻不是。另一方面,php 底層是 c 實現的,學會 c 語言有機會去研究 php 語言本身的實現機制,進而編寫 php 擴展,甚至成爲 php 核心貢獻者。

c 語言簡單而優雅(是的,你沒聽錯),是你真正能直接跟計算機對話的語言(當然你可能要擡槓說是彙編),是深入瞭解操作系統(主要指 Unix 家族)的鑰匙。

c 語言讓你具有微觀視野,知其然而知其所以然。後面說到的數據結構與算法、socket 編程、計算機原理等知識對於熟悉 c 語言的人學起來事半功倍。

數據結構與算法

我想大部分程序員都有(或曾經有)一個學好算法的夢,但大部分中途(甚至是一開始)就放棄了,一方面感覺太難了,另一方面感覺跟實際工作不相關,用不到(這一點和放棄 c 的理由一樣)。

還是那句話,不要認爲實際業務開發中“用不到”的東西就沒有學習的價值,實際情況正好相反,那些實際開發中所謂“用不到”的東西纔是真正要掌握的東西,是平庸和高手之間的分水嶺。

很多 phper 敲了多年代碼,連個遞歸調用都不會寫,一個組織架構功能就把他難倒了,各種奇淫技巧,各種讓人看不懂。

不掌握數據結構與算法,你去閱讀源碼,頂多也就停留在 MVC 框架層面了,稍微底層的東西如數據庫、消息隊列、Web 服務器就根本無從下手。

算法決定一個人的深度。

我建議你去慕課網或者極客時間上買一門課系統地學一下常見的算法。並且手邊還要有一本書(c 語言實現)。

要練習。很多人放棄的原因其實是隻看不練習,前面看後面忘,於是就放棄了。沒有人光通過看能掌握算法的(特別稍微複雜點的算法)。

要總結,寫筆記。每種算法都是一種思想(比如快排的分治思想就是一種通用思想),只有參透了思想纔算真正掌握,才能舉一反三。比如我們掌握了分治思想,不僅僅能用於排序,還能用於大數據批處理中。

熟練掌握遞歸。很多算法都能用遞歸實現。遞歸的本質是整體和部分間存在一致性(重複性),作爲程序員的你要善於發現這種一致性。當一個算法的操作具有重複性時,往往意味着可以用遞歸實現(比如二分查找、快速排序,它們的操作都具有很規律的一致性,因而都能用遞歸實現)。

將所有學到的數據結構和算法先用 c 實現一遍,再用 php 實現一遍(不要認爲 php 跟算法無關,實際是算法跟語言無關)。

計算機與操作系統原理

去看看二進制的世界長什麼樣,CPU 的運作原理,程序的執行過程,操作系統原理等。把這些搞明白後,很多問題會恍然大悟,以前覺得特別複雜的東西比如線程併發、內核態用戶態、緩衝區等現在會覺得特別簡單。

從這些學習中你還會學到很多偉大的設計思想,比如 Unix 中將一切視爲文件、虛擬化(硬件虛擬、虛擬內存等)、抽象(硬件抽象)、大道至簡(CPU 如何通過簡單的與或非異或電路實現複雜的存儲與計算),對你宏觀層面的架構、設計都會有很大幫助。

socket 編程

phper 一輩子都在從事 Web 編程,卻有一大部分 phper 不懂 socket,也搞不懂 php 裏面的 pack、unpack 到底幹嘛用的。

一般高級語言都在底層 socket 上再做了一層封裝,並實現了常用協議如 http 功能,使得我們平時基本碰不到 socket。同樣,這對工程是好事,對程序員的成長卻不是。

比如我們都說 tcp 是流式協議,存在粘包問題,但面試中我問了很多嘗試過 socket 編程的都沒處理過粘包問題,把 tcp 分組當數據報用。

雖然 socket 對底層協議如 tcp、udp 進行了封裝,但如果直接面向 socket 編程,仍然有很多細節需要處理,如粘包、緩衝區、異常等,而這些細節讓我們能更真實地接觸底層知識。

另外,這些底層細節倒逼你去學習 tcp/ip 協議細節,更有甚你會把 tcp/ip 協議簇中的每層都學習一遍,自此你也瞭解了一個請求包在每層到底是怎麼封裝的,一次網絡請求在局域網、廣域網到底是怎麼傳輸的。

真正實踐過,你才能真正搞明白 I/O 多路複用、reactor 事件模型這些看似高大上的東西——不但明白,還能在實際中使用。

熟悉了 socket 編程,你就可以設計自己的應用協議,這時候你就會用上 php 的 pack/unpack(假如你是用 php 寫)。

同樣,我建議買一本講解網絡編程的書,用 c 語言實現的。或者是一本講解網絡協議、tcp/ip 協議的書。同樣是要買經典,不要買什麼 30 天精通、7 天搞定的。

另外,我還是推薦你在慕課網、極客時間等 app 上買一節注重實踐的課程,跟着老師、同行一起學。要買注重實踐、有大量代碼實現的,不要買那種阿貓阿狗比喻滿天飛的。

和算法一樣,我建議你先用 c 語言實現一個 http 服務器(當然如果只是爲了學知識,沒必要做成 nginx),然後再用 php 實現一次。

面向對象、設計原則和設計模式

在面試過程中我發現,大部分工作 5 年的 phper 對設計原則和設計模式都知之甚少,對面向對象也是隻言片語,卻自認爲自己一直在用 OOP。

很多人都認爲這些原則很虛,離自己很遠,實際情況是,相比於 c 語言和算法,面向對象和設計模式離業務程序員更近,也更容易、更需要掌握。

人們常說,程序員都認爲別人寫的代碼都是垃圾。但如果你去看看 laravel 等優秀開源項目的代碼,你還覺得是垃圾嗎?

我們如何在實際工作中寫出開源項目水平的代碼?

換句話說,我們如何寫出可維護、可讀、可擴展、可複用的代碼?

你可能覺得上面一串概念很好聽但很虛,那麼你就想一件事:你在實際項目中看到某些人寫的代碼想罵人,就說明對方的代碼沒有滿足上面的條件;如果再進一步細想,你也不知道如何寫更優,那說明你也沒搞明白麪向對象設計原則,你寫出來的代碼註定也是那樣,註定也會被後人罵。

另一個更可悲的事實是,市面上絕大多數 MVC 框架都是面向過程編程的,卻很少有人意識到這點。絕大部分 MVC 框架的示例程序都是寫個諸如博客文章的增刪改查,控制器裏面寫業務邏輯,Model 層接收並存取數據。這裏至少有兩個問題:

  1. 所有的業務邏輯都寫在控制器裏面,根本沒有對象建模;
  2. Model 實際上是個貧血類(只有屬性沒有行爲,當然有人可能認爲對數據庫的增刪改查是 Model 的行爲,但那實際上只是 Model 委託數據庫驅動去做的事情);

有些 MVC 框架主張在 Model 裏面寫業務邏輯,但這會導致 Model 違反單一職責原則:Model 同時負責了業務邏輯和數據庫操作。

框架們可能認爲對象建模不是他們管的事,通過一個足夠簡單的示例能夠讓使用者更快速的掌握框架,從而獲得更多的粉絲用戶。

但事實是,很少有實際項目是像示例程序那麼簡單的。框架真正的罪責在於:通過一個過於簡化的示例程序引導了一批又一批追隨者們用同樣簡單的方式去實現複雜的業務。

框架設計者們無疑在 OOP、設計模式上有着很深的造詣,但這種造詣僅僅體現在框架本身,卻沒有延展到框架的使用上( Laravel 做得稍微好些)

不過話說回來,OOP 和設計模式是框架不能承載的設計之重,設計本身需要程序員自己去事先掌握,再好的框架也不能讓一個不懂 OOP 設計原則和設計模式的人去使用 OOP 編程(Laravel 在這個方向上給予了指示,僅僅是指示,就讓人們覺得 Laravel 相對於其他框架較難上手了)。

詳細討論 OOP 和設計模式超出了本文範圍,我們着重討論下怎樣學習這些東西。

學習 OOP 和設計模式最重要的是學習 - 實踐 - 複習 - 再實踐,而且,相對於算法,OOP 和設計模式在實際中有更多的機會去實踐,只要你願意,幾乎天天都可以實踐。開發新項目時當然可以實踐,維護就項目也可以實踐,試着用 OOP 設計原則和設計模式去審查既有代碼的問題並執行重構。很多人忽略了重構的價值(以及不知道怎麼重構),於是抱怨說公司沒有合適的新項目去實踐這些原則、模式。下單邏輯中被各種支付方式搞得亂七八糟?不妨把支付抽象成接口吧,試試橋接模式?各種優惠繞得人云裏霧裏?試試策略模式吧;訂單支付回調裏面又是送積分又是發通知,各種後續業務塞不停?試試觀察者模式吧。

你需要買本設計模式的書,相比國內各種禪啊道啊,我建議你直接買 GoF 的《設計模式》,直接面對經典。

讀不懂經典?我再建議你去買一門課程,要買注重實戰的課程。極客時間上的一些課程就相當不錯。不要不捨得花錢。

不要認爲只有單例、工廠、策略、代理常用就只學這幾種,要把 23 種全部掌握。很多設計模式雖然不常用,但一旦遇到對應的場景用上它跟不用它完全是兩個樣子,比如組合模式(composite)。

學習設計模式時,不要將思維侷限於 Web 開發,否則很多模式你會完全不能理解。比如命令模式、備忘錄模式在 Web 開發中很少用到,但在桌面應用中卻很常見,狀態模式則在遊戲開發中很常見。

相對於設計模式,設計原則更難把握,更依賴實踐領悟。比如 SOLID 五原則,光一個單一職責原則,如果沒有足夠的項目開發經驗與反思,都很難真正理解。

設計原則有很多,如 SOLID、GRASP、DRY、KISS,很多原則都是從不同的側面說一個東西,如果你不想把所有的都搞通,建議你着重研究並實踐 SOLID 五原則,我認爲它是最經典、最重要的 OOP 原則。

最後,強烈建議你讀讀《領域驅動設計》這本經典(前提是你要有一定的項目經驗以及 OOP 和設計模式基礎)。

源碼

上面的知識都掌握得差不多的時候,個人建議開始大量擼源碼。

很多人在早期都擼過某些開源項目的源碼,比如 Laravel,但大多半途而廢,原因是看不懂,或者是每段代碼都看懂了,但放一起就看不懂,只知樹木不知森林。原因很簡單:你擼得太早了,上面的知識一個都還沒掌握就開始擼,人家優秀的開源項目各種設計模式各種抽象封裝,擼得動纔怪。你連依賴注入都不知道,如何搞得懂服務容器和服務提供者?

要擼經典項目,star 多的,如 Laravel、composer、phpunit 等。要記筆記,擼出感想。

還要擼 c 項目,如 php 源碼、swoole 等——這也是你學習 c 語言的好機會。

如果這些都擼得不過癮,可以放寬視角,擼其他語言的,可以去擼消息隊列、數據庫、服務器等經典項目,如mysql、kafka、nginx等,只要你有耐心有時間。如果真能擼到這種程度,你遠遠不只是個phper了。

博客

每個程序員都應該寫博客。堅持不斷地寫博客,這點非常重要,我是很晚才意識到這點,以前一直相信一種觀點認爲牛人都很忙,哪有時間寫博客,後面發現牛人都有自己的獨立博客,粉絲量也羨人。

寫博客有兩個最重要的效果:促進自我總結與反思,建立個人品牌。

不過,寫博客的時候不能功利性太強,爲了建立品牌而寫,天天盯着閱讀量。因爲這樣一方面導致你不敢寫,生怕質量不行,一心想憋大招,一文成名,結果是一個月才憋出一篇,結果卻沒人訪問,於是不想寫了。

寫博客的直接目的一定是第一點,促進自我成長,第二點是順帶的、量變到質變的必然過程。

架構

至此,如果你也有一定的項目經驗,你可以重點考慮架構了——因爲此時你已經有微觀(操作系統原理、數據結構與算法)、準宏觀(OOP、設計原則、設計模式)的加持,面對那些高大上的架構設計時,不會知其然不知其所以然。

架構有兩個特點:

  1. 架構是演化出來的,而不是一次性設計出來的。相應地,架構不是學出來的,而是實踐出來的。
  2. 架構裏面的東西大部分是”標價 15 美元,實際只值 5 美分“,所以沒必要被那些高大上的東西唬住。

有個誤區認爲只有大規模公司才需要架構,小公司不需要。

在我認爲,架構要解決兩個層面的複雜性:系統(技術)複雜性和業務複雜性,一般小公司不存在系統複雜性,但極有可能存在業務複雜性(很多小公司爲了快速佔領市場,會開拓各種業務領域)。相應地,架構師可分爲業務架構師和系統架構師。不過很多時候這兩者有很大的交集(比如複雜的業務架構往往需要相應的系統架構如消息中間件的支持,頻繁的對外合作業務則需要開放平臺、應用網關的支持),因而無論你的架構側重點是什麼,你都要在技術和業務兩個維度有較高的修爲。

另一個誤區是,phper 不可能成爲架構師。

的確,從統計意義上說,java 程序員佔絕對優勢,但這不代表說只有 java 程序員才能成爲架構師。架構師跟使用什麼語言沒有必然關係,只是實際中 java 程序員在生態上具有近水樓臺的優勢。架構師更重要的是架構思維,能夠統籌資源解決系統和業務兩個維度的複雜性。不過,就實際來說,因爲很多公司在系統複雜性上來後,會轉而使用 go、java 等靜態語言代替 php、python 這種動態語言,因而,如果一個 phper 想成爲架構師,最好會一門比 c 更高級的靜態語言,個人推薦 go,因爲相對於 java 來說,go 更年輕,競爭對手要少一些(十年的 java 程序員一大把,而兩年的 go 程序員一大把),另外 go 很多地方和 c 類似,如果有很好的 c 基礎,會比較容易深入。

架構師要務實,就如我們在 OOP 時強調不要過度設計一樣,不要過度架構。當你公司的用戶量才十幾萬的時候就搞上各種消息隊列、集羣、分佈式、容器編排,往往會帶來不必要的複雜性,而且由於團隊成員專業能力以及服務治理能力跟不上,可能會導致使用上的混亂。

管理

我在架構後面寫管理,意思很明確:技術管理者需要有一定的架構能力。

我們一般認爲,架構和管理是程序員職業發展的兩個方向,這話沒錯,但不代表兩者沒有重疊,相反,兩者之間有很大重疊。

架構師可以不具備管理能力,但如果他具備的話會如虎添翼。架構師往往需要統籌各方資源,以及規劃整合各業務團隊的公共訴求,需要具備溝通、協調、服務能力。

反過來,優秀的技術管理者則一定要有架構能力。

一方面是服人。雖然說管理要講究技巧,但如果作爲團隊 leader 的你技不如人太多,想必團隊成員很難服你,很多時候你也無法就成員間的分歧給出合理的意見。

更重要的是團隊的成長。一個不具備架構思維的 leader 很難給團隊制定長期成長計劃,也很難做出合理的長期技術選型與技術儲備。

在中小公司,很多管理者是被從技術崗位逼上梁山的,剛開始的時候工作的區別僅是多了一項“分配任務”而已。

從技術到管理,個人認爲需要進行如下思維轉換:

  1. 問題到此爲止。
    我們作爲開發人員的時候,喜歡帥鍋。“這是產品問題,得找產品”、“這是 z 團隊負責的項目,要找他們”、“這是前人留下的 bug”。作爲管理者,要明白這就是你的問題,如果源頭在其他團隊,那你就有責任去協調其他團隊解決問題。
  2. 不要抱怨。
    “前面人腦子生鏽了?寫出這種代碼”、“上面老是壓工時、堆需求”。
    作爲管理者,唯一要做的是解決問題。前人的代碼有問題,組織人去重構;上面壓需求,需要向上管理你的上級。
  3. 不要憤怒。
    你是不是因爲某人寫了一堆爛代碼而朝他大吼?實際問題更可能是他們缺少培訓,而這正是管理者的責任。
  4. 從執行者成爲培育者、老師。
    不要什麼都自己做,那是最差勁的管理者才做的事情。初爲管理者往往會有一種擔憂,認爲如果我不敲代碼,團隊成員會不會認爲我啥都不幹全讓他們幹?另一種擔憂是:其他人不如我,幹不好。讓他人做事,給他人成長的機會。管理者要做的是培訓、幫助。
  5. 從用技術的視角看產品轉成用產品的視角看技術。
  6. 有意識的訓練戰略決策能力(短期主義目光轉換成長期主義目光)。這也是爲啥我強調技術管理者要有架構能力,要能從長期眼光規劃團隊技術發展道路。

未來之路

個人認爲,phper 35 歲後大致有以下幾種職業方向:

  • 創業。有人去做社區電商,有人做外貿,也有人想到個點子和幾個朋友開公司了。
  • 做付費內容。很多博客寫得好或者講座做得好的,適合去做付費內容,現在有很多知識付費平臺如慕課網、極客時間等,一些老牌博客網站如 CSDN 也在做這塊,當然也可以自己建公衆號做付費內容、出書等。這需要你長期積累個人品牌以及較深厚的功底、一定的項目經驗。
  • 技術管理。你可以朝着 CTO 的終極目標前進。這要求你具有較好的架構能力和一定的管理經驗。
  • 架構師。並非每個人都喜歡做管理,有人就喜歡一直鑽研技術。無論是做管理還是做架構,對於 phper 來說,至少要會三門語言:c、php 以及一門更高級的主流靜態語言。
  • 得過且過。很多人到了 35 歲還沒有較明確的職業規劃,跳來跳去還是個普通程序員,就屬於這種。把它作爲一個選項是因爲實際上該類型並不在少數。

總結

迴應本文標題,一句話總結:phper 的未來出路就是不要把自己定位成一個 phper。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章