现在,在小型的计算机科学控制系统中,微服务项目化的控制系统结构设计,成为了绝大部分时候的必定之选。
而怎样将微服务项目做有效率的结构设计,则是须要每两个项目组和技师都须要考量的两个问题。在维持控制系统的连续性、可认知性、可移植性和可扩展性上,须要有一些基本上的辅导准则。
上面撷取微服务项目结构设计和实践中的8个此基础准则,具体内容如下表所示:
基本上准则概要
在微服务项目中,结构设计API时能遵从下列准则:
单个职能准则(Single Responsibility Principle)隐式USB准则(Explicit Interface Principle):API如果明晰和明晰地表述其USB,主要包括输入模块、输入结论和可能的万萨县。这种能提升USB的可认知性和可移植性,增加误为和无谓的沟通交流。界线语句(Bounded Context):根据微服务项目的边界线和销售业务市场需求,分割出相同的界线语句。API的结构设计如果与界线语句相适应,以保证USB的连续性和收敛性。服务项目契约书(Service Contract):API如果建立明晰的服务项目契约书,主要包括USB的语法、协定和版管理。这有利于相同项目组间的协同,保证服务项目间的相容性和整合性。重要信息暗藏(Information Hiding):API如果暗藏外部同时实现技术细节,只曝露必要性的USB。这种能增加对外部同时实现的敏感性,提升服务的自主性和可辅助性。无状况性(Statelessness):尽可能结构设计无状况的API,即不留存应用程序的状况重要信息,每一允诺都如果是分立的。这种能提升服务项目的可扩展性和扩展性。适应能力与重构性(Adaptability and Evolution):API如果具有适应能力和重构性,能够容易地适应相同的市场需求和变化。通过版控制和向后相容性,能使API在不破坏现有应用程序的情况下进行重构和升级。安全性和身份验证(Security and Authentication):API如果提供适当的安全机制和身份验证,以保护服务项目和数据的安全性。这可能主要包括使用加密传输、身份验证令牌和访问控制等措施。接下来,我们将通过日常的一些具体内容demo,来逐个展开这8个准则。
准则具体内容实例
单个职能准则
下列是两个违反单个职能准则的反例,使用Java代码进行演示:
public class UserAPI { public voidcreateUser(String username, String password) { // 创建用户的逻辑 } public void getUserInfo(String username) { } public void updateUser(String username, String newPassword) { // 更新用户密码的逻辑 } public void deleteUser(Stringusername) {// 删除用户的逻辑 } public void sendEmail(String username, String subject, String content) { // 发送邮件的逻辑} }高和可移植性下降的问题。
根据单个职能准则,如果将相同的职能拆分为分立的类或模块。
对于上述例子,能将用户管理和邮件发送拆分为两个单独的类,分别负责各自的功能。这种能提升代码的可读性、可移植性和扩展性。
public class UserManagementAPI { public void createUser(String username, String password) { // 创建用户的逻辑 } public void getUserInfo(String username) { } public void updateUser(String username, StringnewPassword) {// 更新用户密码的逻辑 } public void deleteUser(String username) { // 删除用户的逻辑 } } public class EmailService { public void sendEmail(String username, String subject, String content) { // 发送邮件的逻辑 } }的职能,代码变得更加明晰、可维护,并符合单个职能准则。
隐式USB准则
下列是两个违反隐式USB准则的反例,使用Java代码进行演示:
public class Calculator { public int calculate(int a, int b, String operation) { if (operation.equals(“add”)) { return a + b; } else if (operation.equals(“subtract”)) { return a – b; } else if (operation.equals(“multiply”)) { return a * b; } else if(operation.equals(“divide”)) { return a / b; } return 0; } }在上述代码中,Calculator 类违反了隐式USB准则。它使用了两个字符串模块 operation 来决定进行何种计算操作。这种结构设计方式不明晰和不明晰,没有明晰表述USB和输入输入的结构,使用方在调用时无法准确认知和使用该USB。
根据隐式USB准则,如果明晰和明晰地表述USB,主要包括输入模块、输入结论和可能的万萨县。下列是两个改进的示例:
public interface Calculator { int add(int a, int b); int subtract(int a, int b);int multiply(int a, int b); int divide(int a, int b); }通过表述明晰的USB,使用方能明晰地知道USB的输入和输入,而不须要传递两个字符串模块来确定操作类型。这种能提升USB的可认知性和可移植性,遵从了隐式USB准则。
public class SimpleCalculator implements Calculator { @Override public int add(int a, int b) { return a + b; } @Override public int subtract(int a, int b) { return a – b; } @Override public int multiply(int a, int b) { return a * b; } @Override public int divide(int a, int b) { returna / b; } }通过同时实现明晰的USB,使用方能根据USB表述来调用相应的方法,而无需传递两个字符串模块来指定操作。这种能提升代码的可读性、可移植性和扩展性,并符合隐式USB准则。
界线语句
界线语句准则(Bounded Context)的主要目标是将小型控制系统拆分为相同的语句,每一语句专注于两个特定的销售业务领域,并且在该语句内维持连续性。下列是两个违反界线语句准则的反例:
假设有两个电子商务控制系统,其中包含订单管理和库存管理两个领域。上面是两个违反界线语句准则的同时实现示例:
public class OrderService { public void createOrder(Order order) { // 创建订单的逻辑 } public void updateOrderStatus(Order order, String status) { // 更新订单状况的逻辑 } public void reserveStock(Order order) { // 预留库存的逻辑 } public void releaseStock(Order order) { // 释放库存的逻辑 } public void updateStock(Order order) {// 更新库存的逻辑 } }在上述代码中,OrderService 类同时包含了订单管理和库存管理的逻辑,违反了界线语句准则。如果将这两个销售业务领域拆分为分立的语句,分别负责各自的功能。
public class OrderService { public void createOrder(Order order) { // 创建订单的逻辑 } public void updateOrderStatus(Order order, String status) { // 更新订单状况的逻辑 } } public class InventoryService { public void reserveStock(Order order) { // 预留库存的逻辑 } public void releaseStock(Order order) { // 释放库存的逻辑 } public void updateStock(Order order) { // 更新库存的逻辑 } }的模块化和扩展性。
服务项目契约书
服务项目契约书(Service Contracts)旨在表述服务项目间的明晰契约书,主要包括输入模块、输入结论和可能的万萨县。
假设我们有两个用户管理服务项目,其中有两个方法用于更新用户重要信息。上面是两个违反服务项目契约书准则的示例:
public class UserService { public void updateUser(String userId, String newEmail) { // 更新用户重要信息的逻辑 } }在上述代码中,updateUser 方法只接受用户ID和新的电子邮件地址作为模块,但是它没有返回任何结论或处理任何错误情况。这违反了服务项目契约书准则,因为它没有明晰表述输入模块、输入结论和错误处理。
改进的做法是明晰表述服务项目的契约书,主要包括输入模块、输入结论和错误处理。下列是两个改进的示例:
public class UserService { publicUpdateUserResponseupdateUser(UpdateUserRequest request) { // 更新用户重要信息的逻辑 // … UpdateUserResponse response = newUpdateUserResponse();// 设置更新结论 return response; } } public class UpdateUserRequest { private String userId; private String newEmail; // 其他相关属性和方法 // Getters and setters } public class UpdateUserResponse { private booleansuccess;private String errorMessage; // 其他相关属性和方法 // Getters and setters }通过引入UpdateUserRequest和UpdateUserResponse对象来明晰表述输入模块和输入结论的结构,我们能更好地遵从服务项目契约书准则。使用方能清楚地了解服务项目的输入模块类型、输入结论类型以及怎样处理错误情况。这种能提升代码的可读性、可移植性和扩展性,并保证服务项目间的契约书明晰。
重要信息暗藏
重要信息暗藏准则(Information Hiding Principle)是面向对象结构设计中的两个准则,它强调将类的外部技术细节暗藏起来,只曝露必要性的USB给外部使用。
下列是两个违反重要信息暗藏准则的反例:
public class BankAccount { public String accountNumber; public String accountHolder; public double balance; public void deposit(double amount) { balance += amount; } public void withdraw(double amount) { balance -= amount; } public void displayAccountInfo() { System.out.println(“Account Number: “ + accountNumber); System.out.println(“Account Holder: “ + accountHolder); System.out.println(“Balance: “ + balance); } }在上述代码中,BankAccount 类违反了重要信息暗藏准则。它将账户号码、账户持有人和余额都声明为公共的属性,可以被外部直接访问和修改。同时,displayAccountInfo 方法也直接打印账户重要信息到控制台。
改进的做法是将类的外部状况和同时实现技术细节封装起来,只提供必要性的USB供外部访问和操作。下列是两个改进的示例:
public class BankAccount { private String accountNumber; private String accountHolder; private doublebalance;public BankAccount(String accountNumber, String accountHolder) { this.accountNumber = accountNumber; this.accountHolder = accountHolder; this.balance = 0; } public void deposit(double amount){ balance += amount; }public void withdraw(double amount) { balance -= amount; } public void displayAccountInfo() { System.out.println(“Account Number: “ + accountNumber); System.out.println(“Account Holder: “ + accountHolder); System.out.println(“Balance: “ + balance); } }在改进后的代码中,将账户的属性声明为私有,并提供了公共的方法来进行存款、取款和显示账户重要信息的操作。外部代码无法直接访问和修改账户的外部状况,只能通过提供的USB来与账户对象进行交互,保护了类的外部同时实现技术细节并提升了封装性。
无状况性
无状态性准则(Statelessness Principle)强调在结构设计中避免留存应用程序的状况重要信息,每一允诺如果是分立且自包含的。
下列是两个违反无状况性准则的反例:
public class ShoppingCart { private List<Item> items; private double totalPrice; public void addItem(Item item) { items.add(item); totalPrice += item.getPrice(); }public void removeItem(Item item) { items.remove(item); totalPrice -= item.getPrice(); }public double getTotalPrice() { return totalPrice; } // 其他方法 }在上述代码中,ShoppingCart 类留存了应用程序的状况重要信息,主要包括购物车中的商品列表和总价格。每次添加或移除商品时,都会更新购物车中的商品列表和总价格。这违反了无状况性准则,因为购物车的状况重要信息依赖于之前的操作,并且随着时间的推移会发生变化。
改进的做法是使购物车变得无状况,每一允诺都是分立的。下列是两个改进的示例:
public class ShoppingCart { public double calculateTotalPrice(List<Item> items) { double totalPrice = 0; for(Item item : items) { totalPrice += item.getPrice(); }return totalPrice; } // 其他方法 }在改进后的代码中,我们将购物车改为两个无状况的类,不留存任何状况重要信息。相反,我们提供了两个 calculateTotalPrice 方法,接收商品列表作为模块,并根据传入的列表计算总价格。每次调用该方法时,都是分立的,不依赖于之前的操作,维持了无状况性。
这种结构设计能更好地遵从无状况性准则,使每一允诺都是分立的,无需留存应用程序的状况重要信息,提升了可扩展性和可靠性。
适应能力与重构性
适应能力与重构性准则(Adaptability and Evolvability Principle)强调控制系统的结构设计应具备适应变化和重构的能力,能够灵活应对新市场需求和技术的引入。
下列是两个违反适应能力与重构性准则的反例:
public class PaymentService { public void processPayment(String paymentMethod,double amount) { if (paymentMethod.equals(“creditCard”)) { // 处理信用卡支付逻辑 System.out.println(“Processing credit card payment…”); } else if (paymentMethod.equals(“paypal”)) { // 处理PayPal支付逻辑System.out.println(“Processing PayPal payment…”); } else if (paymentMethod.equals(“applePay”)) { // 处理Apple Pay支付逻辑 System.out.println(“Processing Apple Pay payment…”); } else { throw newIllegalArgumentException(“Unsupported payment method”); } } // 其他方法 }在上述代码中,PaymentService 类中的 processPayment 方法根据传入的支付方式进行相应的支付处理。这种同时实现方式违反了适应能力与重构性准则,因为当引入新的支付方式时,须要修改 processPayment 方法的代码来添加新的逻辑分支。
改进的做法是通过USB和策略模式来同时实现支付方式的适应能力和重构性。下列是两个改进的示例:
public interface PaymentMethod { void processPayment(double amount); }public class CreditCardPayment implements PaymentMethod { @Override public void processPayment(doubleamount) { // 处理信用卡支付逻辑 System.out.println(“Processing credit card payment…”); } } public class PayPalPayment implements PaymentMethod { @Override public void processPayment(double amount) { // 处理PayPal支付逻辑System.out.println(“Processing PayPal payment…”); } } public class ApplePayPayment implements PaymentMethod { @Override public void processPayment(double amount) { // 处理Apple Pay支付逻辑 System.out.println(“Processing Apple Pay payment…”); } } public class PaymentService { public void processPayment(PaymentMethod paymentMethod,double amount) { paymentMethod.processPayment(amount); } // 其他方法 }在改进后的代码中,我们定义了两个 PaymentMethod USB,并为每种支付方式同时实现了具体内容的同时实现类。
PaymentService 类的 processPayment 方法接收两个 PaymentMethod 对象作为模块,并调用相应的支付方式的 processPayment 方法进行支付处理。
通过USB和策略模式的使用,我们使得支付方式的添加和修改变得更加灵活和可扩展,符合适应能力与重构性准则。
安全性和身份验证
安全性和身份验证准则(Security and Authentication Principle)强调在控制系统结构设计中如果考量安全性市场需求,并采取适当的身份验证措施来保护控制系统和用户的安全。
下列是两个违反安全性和身份验证准则的反例:
public class UserController { public UserDTO getUser(String userId) { // 根据用户ID查询用户重要信息 returnuserRepository.findUserById(userId); }public void updateUser(String userId, UserDTO updatedUser) { // 更新用户重要信息userRepository.updateUser(userId, updatedUser); }// 其他方法 }改进的做法是引入身份验证和安全性措施来保护用户重要信息。下列是两个改进的示例:
public classUserController {private AuthenticationService authenticationService; private UserRepository userRepository; public UserDTO getUser(String userId, String authToken) { if(!authenticationService.isAuthenticated(authToken)) {throw new SecurityException(“Unauthorized access”); } // 根据用户ID查询用户重要信息 returnuserRepository.findUserById(userId); }public void updateUser(String userId, UserDTO updatedUser, String authToken) { if (!authenticationService.isAuthenticated(authToken)) { throw new SecurityException(“Unauthorized access”); } // 更新用户重要信息 userRepository.updateUser(userId, updatedUser); } // 其他方法 }在改进后的代码中,我们引入了 Authent
如果身份验证失败,将抛出两个安全异常,阻止未经授权的访问。
这种,用户重要信息的访问和修改将受到身份验证和安全性保护,符合安全性和身份验证准则。
最后
以上的8个基本上准则,能作为我们日常结构设计微服务项目API的辅导,来帮助项目组保证服务项目的连续性、可认知性、可移植性和扩展性。
然而,具体内容的微服务项目的API结构设计,还应根据具体内容的项目的特定市场需求、项目组的技术栈和销售业务场景做出适当的调整和决策。