架構師日記-聊聊開發必掌握的那些實踐技能
構建語言生態的優勢,彌補其存在短板,始終是程式語言的一個演進方向。
1999年,美國太空總署(NASA)的火星任務失敗:在這次任務中,火星氣候探測者號上的飛行系統軟體使用公制單位牛頓計算推進器動力,而地面人員輸入的方向校正量和推進器引數則使用英制單位磅力,導致探測器進入大氣層的高度有誤,最終瓦解碎裂。
2.1 關於命名
蛇形命名法(snake case):又叫下劃線命名法,使用下劃線,單詞小寫,比如:my_system; 駝峰命名法(camel case):按照單詞首字母區分大小寫,又可細分為大駝峰命名法和小駝峰命名法,比如:MySystem,mySystem; 匈牙利命名法(HN case):屬性+型別+描述,比如:nLength,g_cch,hwnd; 帕斯卡命名法(Pascal case):全部首字母大寫,等同於大駝峰命名法,比如:MySystem; 脊柱命名法(spinal case):使用中劃線,比如:my-system; 自由命名法(studly caps):大小寫混雜,無簡明規則,比如:mySYSTEM,MYSystem;
2.1.1 命名字典
2.1.2 命名實踐
專案名全部小寫; 包名全部小寫; 類名首字母大寫,其餘組成詞首字母依次大寫; 變數名,方法名首字母小寫,如果名稱由多個單片語成,除首字母外的每個單詞首字母都要大寫; 常量名全部大寫;
自帶混淆功能的變數名:String zhrmghg = "極致縮寫型"; 沒有意義的萬能變數名:String a,b,c="愛誰誰型"; 長串拼音變數名:String HuaBuHua = "考古型"; 各種符號混用:String $my_first_name_ = "打死記不住型"; 大小寫,數字,縮寫混亂:String waitRPCResponse1 = "極易出錯型";
public <PropertyType> get<PropertyName>(); public void set<PropertyName>(<PropertyType> p)
public boolean is<PropertyName>(); public void set<PropertyName>(boolean p)
一類是同一個jar包出現了多個不同的版本。應用選擇了錯誤的版本導致jvm載入不到需要的類或者載入了錯誤版本的類;(藉助maven管理工具相對容易解決) 另一類是不同的jar包出現了類路徑相同的類,同樣的類出現在不同的依賴jar裡,由於jar載入的先後順序導致了JVM載入了錯誤版本的類;(比較難以解決)
public class SkuKey implements Serializable { @JsonProperty(value = "sn") @ApiModelProperty(name = "stationNo", value = " 門店編號", required = true) private Long stationNo; @JsonProperty(value = "si") @ApiModelProperty(name = "skuId", value = " 商品編號", required = true) private Long skuId; // 省略get/set方法}
2.2 關於註釋
2.2.1 好的註釋
系統註釋:透過README.md檔案體現宏觀的功能和架構實現; 包註釋:透過package-info檔案體現模組職責邊界,另外該檔案也支援宣告友好類,包常量以及為標註在包上的註解(Annotation)提供便利; 類註釋:主要體現功能職責,版本支援,作者歸屬,應用示例等相關資訊; 方法註釋:關注入參,出參,異常處理宣告,使用場景舉例等相關內容; 程式碼塊和程式碼行註釋:主要體現邏輯意圖,閉坑警示,規劃TODO,放大關注點等細節內容;
2.2.2 壞的註釋
冗餘式:如果一個函式,讀者能夠很容易的就讀出來程式碼要表達的意思,註釋就是多餘的; 錯誤式:如果註釋地不清楚,甚至出現歧義,那還不如不寫; 簽名式:類似“add by liuhuiqing 2023-08-05”這種註釋,容易過期失效而且不太可信(不能保證所有人每次都採用這種方式註釋),其功能完全可以由git程式碼管理工具來實現; 長篇大論式:程式碼塊裡,夾雜了大篇幅的註釋,不僅影響程式碼閱讀,而且維護困難; 非本地註釋:註釋應該在離程式碼實現最近的地方,比如:被呼叫的方法註釋就由方法本身來維護,呼叫方無需對方法做詳細的說明; 註釋掉的程式碼:無用的程式碼應該刪除,而不是註釋。歷史記錄交給git等程式碼管理工具來維護;
2.3 關於分層
2.3.1 系統分層
2.3.2 軟體伸縮性
軟體伸縮性指的是軟體系統在面對負載壓力時,能夠保持原有效能並擴充套件以支援更多工的能力。
伸縮性可以有兩個方面,垂直伸縮性和水平伸縮性,垂直伸縮性是透過在同一個業務單元中增加資源來提高系統的吞吐量,比如增加伺服器cpu的數量,增加伺服器的記憶體等。水平伸縮性是透過增加多個業務單元資源,使得所有的業務單元邏輯上就像是一個單元一樣。比如ejb分散式元件模型,微服務元件模型等都屬於此種方式。
2.4 小結
3.1 類定義
3.1.1 常量定義
public enum Color { RED, GREEN, BLUE;}
public class MyClass { public static final int MAX_VALUE = 100;}
3.1.2 工具類
public abstract class ObjectHelper { public static boolean isEmpty(String str) { return str == null || str.length() == 0; }}
3.1.3 JavaBean
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
import lombok.Data;
true) (chain =
public class Person {
private String name;
private int age;
}
3.1.4 不可變類
public final class String implements Serializable, Comparable<String>, CharSequence {
}
java.lang.Stringjava.lang.Mathjava.lang.Booleanjava.lang.Characterjava.util.Datejava.sql.Datejava.lang.Systemjava.lang.ClassLoader
3.1.5 匿名內部類
直接作為引數傳遞給方法或建構函式;
用於實現某個介面或抽象類的匿名例項;
public class Example { public static void main(String[] args) { // 建立一個匿名內部類 Runnable runnable = new Runnable() { @Override public void run() { System.out.println("Hello, World!"); } }; // 呼叫匿名內部類的方法 runnable.run(); }}
3.1.6 宣告類
AutoCloseable:表示實現了該介面的類可以被自動關閉,通常用於資源管理。 Comparable:表示實現了該介面的類可以與其他實現了該介面的物件進行比較。 Callable:表示實現了該介面的類可以作為引數傳遞給執行緒池,並返回結果。 Cloneable:表示實現了該介面的類可以被克隆。 Enum:表示實現了該介面的類是一個列舉型別。 Iterable:表示實現了該介面的類可以迭代。 Runnable:表示實現了該介面的類可以作為執行緒執行。 Serializable:表示實現了該介面的類可以被序列化和反序列化。 interface:表示實現了該介面的類是一個介面,可以包含方法宣告。 Annotation:表示實現了該介面的類是一個註解,可以用於後設資料描述。
3.1.7 Record 類
/** * 關鍵定義的類是不可變類 * 將所有成員變數透過引數的形式定義 * 預設會生成全部引數的構造方法 * @param name * @param age */public record Person(String name, int age) { public Person{ if(name == null){ throw new IllegalArgumentException("提供緊湊的方式進行引數校驗"); } } /** * 定義的類中可以定義靜態方法 * @param name * @return */ public static Person of(String name) { return new Person(name, 18); }}
Person person = new Person("John", 30);// Person person = Person.of("John");String name = person.name();int age = person.age();
public List<Person> sortPeopleByAge(List<Person> people) {
record Data(Person person, int age){};
return people.stream()
.map(person -> new Data(person, computAge(person)))
.sorted((d1, d2) -> Integer.compare(d2.age(), d1.age()))
.map(Data::person)
.collect(toList());
}
public int computAge(Person person) {
return person.age() - 1;
}
3.1.8 密封類
final修飾類,這樣類就無法被繼承了; package-private類,可以控制只能被同一個包下的類繼承;
sealed class SealedClass permits SubClass1, SubClass2 {
}
class SubClass1 extends SealedClass {
}
class SubClass2 extends SealedClass {
}
3.2 方法定義
3.2.1 構造方法
public class MyClass {
private int myInt;
private String myString;
// 構造方法
public MyClass(int myInt, String myString) {
this.myInt = myInt;
this.myString = myString;
}
}
3.2.2 方法重寫
class Animal {
public void makeSound() {
System.out.println("Animal is making a sound");
}
}
class Cat extends Animal {
public void makeSound() {
System.out.println("Meow");
}
}
public class Main {
public static void main(String[] args) {
Animal myCat = new Cat();
myCat.makeSound(); // 輸出 "Meow"
}
}
3.2.3 方法過載
public class Calculator {
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
}
public class Main {
public static void main(String[] args) {
Calculator calculator = new Calculator();
int result1 = calculator.add(2, 3);
double result2 = calculator.add(2.5, 3.5);
System.out.println(result1); // 輸出 5
System.out.println(result2); // 輸出 6.0
}
}
3.2.4 匿名方法
public static void main(String args[]) {
List<String> names = Arrays.asList("hello", "world");
// 使用 Lambda 表示式作為引數傳遞給 forEach 方法
names.forEach((String name) -> System.out.println("Name: " + name));
// 使用 Lambda 表示式作為獨立表示式使用
Predicate<String> nameLengthGreaterThan5 = (String name) -> name.length() > 5;
boolean isLongName = nameLengthGreaterThan5.test("John");
System.out.println("Is long name? " + isLongName);
}
3.3 物件定義
3.3.1 單例物件
控制資源的使用:透過執行緒同步來控制資源的併發訪問。 控制例項產生的數量:達到節約資源的目的。 作為通訊媒介使用:也就是資料共享,它可以在不建立直接關聯的條件下,讓多個不相關的兩個執行緒或者程式之間實現通訊。
public enum Singleton { INSTANCE; public void someMethod() { // ...其他程式碼... }}
3.3.2 不可變物件
將物件的狀態儲存在不可變物件中:String、Integer等就是內建的不可變物件型別; 將物件的狀態儲存在final變數中:final變數一旦被賦值就不能被修改; 將物件的所有屬性都設為不可變物件:這樣就可以確保整個物件都是不可變的;
Collections.unmodifiableList(new ArrayList<>());
3.3.3 元組物件
public class Pair<A,B> {
public final A first;
public final B second;
public Pair(A a, B b) {
this.first = a;
this.second = b;
}
public A getFirst() {
return first;
}
public B getSecond() {
return second;
}
}
public class Triplet<A,B,C> extends Pair<A,B>{
public final C third;
public Triplet(A a, B b, C c) {
super(a, b);
this.third = c;
}
public C getThird() {
return third;
}
public static void main(String[] args) {
// 表示姓名,性別,年齡
Triplet<String,String,Integer> triplet = new Triplet("John","男",18);
// 獲得姓名
String name = triplet.getFirst();
}
}
public class Tuple<E> {
private final E[] elements;
public Tuple(E... elements) {
this.elements = elements;
}
public E get(int index) {
return elements[index];
}
public int size() {
return elements.length;
}
public static void main(String[] args) {
// 表示姓名,性別,年齡
Tuple<String> tuple = new Tuple<>("John", "男", "18");
// 獲得姓名
String name = tuple.get(0);
}
}
儲存多個資料元素:Tuple可以儲存多個不同型別的資料元素,這些元素可以是基本型別、物件型別、陣列等; 簡化程式碼:Tuple可以使程式碼更加簡潔,減少重複程式碼的編寫。透過Tuple,我們可以將多個變數打包成一個物件,從而減少了程式碼量; 提高程式碼可讀性:Tuple可以提高程式碼的可讀性。透過Tuple,我們可以將多個變數打包成一個物件,從而使程式碼更加易讀; 支援函式返回多個值:Tuple可以支援函式返回多個值。在Java中,函式只能返回一個值,但是透過Tuple,我們可以將多個值打包成一個物件返回;
NamedTuple namedTuple = Tuples.named("person", "name", "age");
3.3.4 臨時物件
儘量重用物件。由於系統不僅要花時間生成物件,以後可能還需花時間對這些物件進行垃圾回收和處理,因此,生成過多的物件將會給程式的效能帶來很大的影響,重用物件的策略有快取物件,也可以針對具體場景進行定向最佳化,比如使用StringBuffer代替字串拼接的方式; 儘量使用區域性變數。呼叫方法時傳遞的引數以及在呼叫中建立的臨時變數都儲存在棧中,速度較快。其他變數,如靜態變數、例項變數等,都在堆中建立,速度較慢; 分代收集。分代垃圾回收策略,是基於這樣一個事實:不同的物件的生命週期是不一樣的。因此,不同生命週期的物件可以採取不同的收集方式,以便提高回收效率;
3.3.5 Valhalla
效能增強透過展平物件圖和移除間接來解決。這將獲得更高效的記憶體佈局和更少的分配和垃圾回收。
當用作泛型類型時,原語和物件具有更相似的行為,這是更好的抽象。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70027824/viewspace-2987040/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 架構師日記—聊聊開發必掌握的那些實踐技能架構
- 架構師日記-軟體高可用實踐那些事兒架構
- 架構師之路:一個架構師需要掌握的知識技能架構
- 優秀前端開發工程師必須掌握的七大技能前端工程師
- 前端架構師破局技能,NodeJS 落地 WebSocket 實踐前端架構NodeJSWeb
- 阿里架構師Peter老師講述Java程式設計師→架構師所需要掌握的技能阿里架構Java程式設計師
- Java架構師必備技能:docker使用大全Java架構Docker
- 架構師必備:多維度查詢的最佳實踐架構
- 個人總結的一箇中高階Java開發工程師或架構師需要掌握的一些技能Java工程師架構
- Java開發需要掌握哪些技術?Java程式設計師必備技能Java程式設計師
- java程式設計師進階架構師你必須掌握的架構知識體系Java程式設計師架構
- 架構師所需的硬實力與軟技能架構
- 架構師必備的那些分散式事務解決方案!!架構分散式
- 走向架構師——1~3年java程式設計師面試必備的技能架構Java程式設計師面試
- 架構必備技能第一談架構
- 阿里大資料架構師必備技能,你“佩奇”了嘛?阿里大資料架構
- JAVA架構師那些事?Java架構
- 作為一名合格的JAVA架構師需要點亮那些技能樹?Java架構
- 面試筆記之必掌握的java核心技能點面試筆記Java
- [開發故事]架構師修煉 III - 掌握設計原則架構
- 架構師必備:巧用Canal實現非同步、解耦的架構架構非同步解耦
- 大資料開發工程師需要掌握什麼技能?大資料工程師
- 掌握11項技能,你就是優秀的前端開發工程師前端工程師
- 聊聊程式設計師面試時,那些必須注意的事情程式設計師面試
- React專案架構,掌握前端架構師的核心本領React架構前端
- 微服務架構技術棧:程式設計師必須掌握的微服務架構框架詳細解析微服務架構程式設計師框架
- CSS中那些必須掌握的概念CSS
- 招聘golang開發&架構師Golang架構
- 開發網站的必備技能網站
- 軟體架構師需要具備的技能 - Abeysinghe架構
- [- Flutter必備 -] 聊聊那些彈框Flutter
- 一名合格的前端開發工程師應該掌握的8個技能前端工程師
- 聊聊資料人的職場必備技能
- 乾淨架構在 Web 服務開發中的實踐架構Web
- Java程式設計師微服務架構你必須要掌握的十個要點Java程式設計師微服務架構
- 架構師必須掌握的各種編碼:ASCII、ISO-8859-1、GB2312架構ASCII
- 【架構師成長必備】如何閱讀一個開源專案的原始碼?【石杉的架構筆記】架構原始碼筆記
- 2017.3.14java方向必備技能掌握Java