关注点分离:提升软件设计的清晰度与灵活性

举报
肖哥弹架构 发表于 2024/11/26 18:20:22 2024/11/26
【摘要】 在软件架构中,关注点分离(Separation of Concerns, SoC)是一种至关重要的设计原则,它帮助开发者构建更加模块化、灵活且易于维护的系统。通过将不同的功能和业务逻辑分离到不同的组件中,我们可以降低系统的复杂性,提高代码的可读性和可维护性。

image.png
在软件架构中,关注点分离(Separation of Concerns, SoC)是一种至关重要的设计原则,它帮助开发者构建更加模块化、灵活且易于维护的系统。通过将不同的功能和业务逻辑分离到不同的组件中,我们可以降低系统的复杂性,提高代码的可读性和可维护性。

1. 关注点分离设计图:

标准分层架构图描述

  1. 表示层(Presentation Layer)
    • 这一层负责处理用户界面和用户体验。
    • 它与用户直接交互,收集用户输入并展示数据。
  2. 业务逻辑层(Business Logic Layer)
    • 这一层包含应用程序的核心业务逻辑。
    • 它处理数据的加工、验证和业务规则的应用。
  3. 数据访问层(Data Access Layer)
    • 这一层负责与数据库或其他持久化存储交互。
    • 它封装了所有数据的检索、更新、保存和删除操作。
  4. 数据层(Data Layer)
    • 这一层涉及到数据模型和数据库表。
    • 它代表了数据的物理存储。
  5. 服务层(Service Layer)
    • (可选)这一层可以进一步抽象业务逻辑,为表示层和业务逻辑层提供服务。
  6. 基础设施层(Infrastructure Layer)
    • 包括硬件、网络资源、消息队列、缓存等基础设施组件。

2、关注点分离的设计哲学

  • 单一职责:每个组件只负责一个单一的功能或业务逻辑。
  • 解耦合:组件之间的依赖关系最小化,提高系统的灵活性。

3、关注点分离解决什么

  • 降低复杂性:通过分离不同的关注点,系统变得更加简洁。
  • 增强可维护性:独立的组件更容易维护和升级。

4、关注点分离的特点

  • 模块化:系统被划分为多个模块,每个模块封装特定的功能。
  • 高内聚低耦合:每个模块具有高内聚性,模块间的耦合度低。

5、关注点分离的缺点

  • 过度分离:不恰当的分离可能导致系统碎片化,增加理解和维护的难度。
  • 设计挑战:需要精心设计组件的接口和交互,以实现有效的分离。

6、关注点分离使用场景

关注点分离适用于所有需要良好结构和可维护性的软件项目,尤其是在大型和复杂的系统中。

7、关注点分离案例

7.1 博客文章发布案例

博客文章发布系统通常包含以下业务逻辑:

  1. 文章创建:允许用户输入文章的标题、内容,并提交文章。
  2. 文章存储:将文章数据持久化到数据库。
  3. 文章审核:对提交的文章进行内容审核,确保符合发布标准。
  4. 文章发布:将审核通过的文章设置为公开状态,使其对读者可见。
  5. 文章检索:允许用户根据标题、内容或作者等条件检索文章。
  6. 文章更新和删除:允许作者或管理员更新或删除文章。

代码下方有分离的依据,先看代码。

// 博客文章实体
public class BlogPost {
    private String id;
    private String title;
    private String content;
    private boolean isPublished;

    // 构造器、getter和setter省略
}

// 用户实体
public class User {
    private String id;
    private String username;
    private String permission; // 例如:ROLE_ADMIN, ROLE_USER

    // 构造器、getter和setter省略
}

// 评论实体
public class Comment {
    private String id;
    private String content;
    private String blogPostId; // 关联的文章ID

    // 构造器、getter和setter省略
}

// 通知实体
public class Notification {
    // 通知内容和相关属性
}

// 用户活动跟踪实体
public class UserActivity {
    // 用户活动详情
}

// 用户数据访问接口
public interface UserRepository {
    User findById(String id);
    void save(User user);
    // 其他用户相关数据访问方法
}

// 用户数据访问实现
public class UserRepositoryImpl implements UserRepository {
    // 使用内存存储数据库
    private Map<String, User> storage = new HashMap<>();
    
    // 实现方法...
}

// 文章数据访问接口
public interface BlogPostRepository extends JpaRepository<BlogPost, String> {
    List<BlogPost> findByKeyword(String keyword);
    // 其他文章相关数据访问方法
}

// 文章数据访问实现
public class BlogPostRepositoryImpl extends JpaRepository<BlogPost, String> {
    // 使用JPA实现数据库操作
}

// 评论数据访问接口
public interface CommentRepository extends JpaRepository<Comment, String> {
    // 评论相关数据访问方法
}

// 评论数据访问实现
public class CommentRepositoryImpl extends JpaRepository<Comment, String> {
    // 使用JPA实现数据库操作
}

// 用户服务接口
public interface UserService {
    User createUser(User user);
    void updatePermission(String userId, String permission);
    // 其他用户管理相关方法
}

// 用户服务实现
public class UserServiceImpl implements UserService {
    private UserRepository userRepository;

    @Autowired
    public UserServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public User createUser(User user) {
        // 创建用户逻辑
        return userRepository.save(user);
    }

    @Override
    public void updatePermission(String userId, String permission) {
        // 更新用户权限逻辑
        User user = userRepository.findById(userId).orElseThrow();
        user.setPermission(permission);
        userRepository.save(user);
    }
    // 其他方法实现...
}

// 内容管理服务接口
public interface ContentService {
    BlogPost saveDraft(BlogPost blogPost);
    BlogPost publish(BlogPost blogPost);
    BlogPost update(BlogPost blogPost);
    void delete(String id);
    // 其他内容管理相关方法
}

// 内容管理服务实现
public class ContentServiceImpl implements ContentService {
    private BlogPostRepository repository;

    @Autowired
    public ContentServiceImpl(BlogPostRepository repository) {
        this.repository = repository;
    }

    @Override
    public BlogPost saveDraft(BlogPost blogPost) {
        // 保存草稿逻辑
        return repository.save(blogPost);
    }

    @Override
    public BlogPost publish(BlogPost blogPost) {
        // 发布文章逻辑
        blogPost.setPublished(true);
        return repository.save(blogPost);
    }

    @Override
    public BlogPost update(BlogPost blogPost) {
        // 更新文章逻辑
        return repository.save(blogPost);
    }

    @Override
    public void delete(String id) {
        // 删除文章逻辑
        repository.deleteById(id);
    }
    // 其他方法实现...
}

// 审核服务接口
public interface ReviewService {
    void conductReview(BlogPost blogPost) throws ReviewException;
}

// 审核服务实现
public class ReviewServiceImpl implements ReviewService {
    // 审核服务逻辑,可能包括调用外部API或复杂的业务规则
    @Override
    public void conductReview(BlogPost blogPost) throws ReviewException {
        // 审核文章内容
        if (/* 审核条件 */) {
            throw new ReviewException("Content does not meet the criteria.");
        }
    }
}

// 发布服务接口
public interface PublishService {
    BlogPost publishArticle(BlogPost blogPost) throws ReviewException;
}

// 发布服务实现
public class PublishServiceImpl implements PublishService {
    private ContentService contentService;
    private ReviewService reviewService;

    @Autowired
    public PublishServiceImpl(ContentService contentService, ReviewService reviewService) {
        this.contentService = contentService;
        this.reviewService = reviewService;
    }

    @Override
    public BlogPost publishArticle(BlogPost blogPost) throws ReviewException {
        reviewService.conductReview(blogPost);
        return contentService.publish(blogPost);
    }
}

// 互动服务接口
public interface InteractionService {
    void addComment(Comment comment);
    // 其他互动相关方法
}

// 互动服务实现
public class InteractionServiceImpl implements InteractionService {
    private CommentRepository commentRepository;

    @Autowired
    public InteractionServiceImpl(CommentRepository commentRepository) {
        this.commentRepository = commentRepository;
    }

    @Override
    public void addComment(Comment comment) {
        // 添加评论逻辑
        commentRepository.save(comment);
    }
    // 其他方法实现...
}

// 搜索服务接口
public interface SearchService {
    List<BlogPost> searchByKeyword(String keyword);
    // 其他搜索相关方法
}

// 搜索服务实现
public class SearchServiceImpl implements SearchService {
    private BlogPostRepository blogPostRepository;

    @Autowired
    public SearchServiceImpl(BlogPostRepository blogPostRepository) {
        this.blogPostRepository = blogPostRepository;
    }

    @Override
    public List<BlogPost> searchByKeyword(String keyword) {
        // 根据关键词搜索文章逻辑
        return blogPostRepository.findByKeyword(keyword);
    }
    // 其他方法实现...
}

// 通知服务接口
public interface NotificationService {
    void sendNotification(Notification notification);
    // 其他通知相关方法
}

// 通知服务实现
public class NotificationServiceImpl implements NotificationService {
    // 发送通知逻辑,可能包括邮件、短信或实时消息
    @Override
    public void sendNotification(Notification notification) {
        // 发送通知实现
    }
}

// 统计分析服务接口
public interface AnalyticsService {
    void trackUserActivity(UserActivity activity);
    // 其他统计分析相关方法
}

// 统计分析服务实现
public class AnalyticsServiceImpl implements AnalyticsService {
    // 跟踪用户活动逻辑
    @Override
    public void trackUserActivity(UserActivity activity) {
        // 记录用户行为数据
    }
}

// 自定义异常:审核不通过异常
public class ReviewException extends Exception {
    public ReviewException(String message) {
        super(message);
    }
}

// 客户端应用程序
public class BlogApplication {
    public static void main(String[] args) {
        // 依赖注入和系统启动逻辑
        // ApplicationContext context = ...;
        // Autowire services where needed

        // 发布文章流程
        try {
            BlogPost blogPost = new BlogPost(/* 属性 */);
            PublishService publishService = context.getBean(PublishService.class);
            BlogPost publishedPost = publishService.publishArticle(blogPost);
            System.out.println("Article published successfully!");
        } catch (ReviewException e) {
            System.err.println("Failed to publish article: " + e.getMessage());
        }
    }
}

8、 博客业务范围与分离

  1. 内容管理
    • 范围:涉及文章内容的存储、呈现和维护。
    • 分离思路:内容是博客系统的核心,需要专门的服务来处理与内容相关的逻辑。
  2. 用户管理
    • 范围:包括用户账户的创建、权限分配和个人资料管理。
    • 分离思路:用户是系统交互的主体,需要一套机制来管理用户信息和权限。
  3. 审核流程
    • 范围:文章发布前的质量控制和合规性检查。
    • 分离思路:保证发布内容的质量和一致性,避免违规内容的发布。
  4. 发布控制
    • 范围:文章从草稿到发布的转换,包括版本控制和状态管理。
    • 分离思路:管理文章的生命周期,确保内容按计划发布。
  5. 互动功能
    • 范围:包括评论、点赞、分享等用户与文章的交互。
    • 分离思路:提升用户参与度,增强社区互动。
  6. 搜索与导航
    • 范围:允许用户通过关键词、分类、标签等方式检索文章。
    • 分离思路:帮助用户快速找到感兴趣的内容。
  7. 通知服务
    • 范围:用户行为或系统事件触发的通知,如评论回复、文章更新等。
    • 分离思路:保持用户对系统动态的及时了解。
  8. 统计分析
    • 范围:对用户行为和内容表现进行跟踪和分析。
    • 分离思路:为内容创作和系统优化提供数据支持。

8.1 分离的依据与案例

  • 依据:分离的依据通常是基于业务功能的独立性、技术实现的差异性、团队分工的需要以及系统的可维护性和可扩展性。
  • 分离维度: 业务逻辑分离、系统结构分离、处理流程分离、性能分离、安全分离、数据持久化分离、用户界面分离、测试分离、配置和基础设施分离
  • 案例
    • 内容管理ContentService负责处理文章的保存、更新和删除。例如,当用户提交新文章时,ContentService中的saveDraft()方法被调用。
    • 用户管理UserService管理用户账户和权限。例如,grantPermission()方法用于更新用户的角色或访问级别。
    • 审核流程ReviewService执行文章的审核工作。例如,在文章提交后,ReviewServiceconductReview()方法确保内容符合发布标准。
    • 发布控制PublishService控制文章的状态转换。例如,publishArticle()方法将文章状态从草稿更改为已发布。
    • 互动功能InteractionService处理评论和点赞。例如,addComment()方法允许用户在文章下留言。
    • 搜索与导航SearchService提供搜索功能。例如,searchArticles()方法根据用户查询返回相关文章。
    • 通知服务NotificationService发送更新通知。例如,当用户的文章被评论时,sendCommentNotification()方法触发通知发送。
    • 统计分析AnalyticsService跟踪和报告用户行为。例如,trackUserActivity()方法记录用户的阅读习惯和偏好。

9、参考开源框架

许多现代应用程序和框架,如Spring和Hibernate,都采用了关注点分离的原则来设计其架构,以提高代码的模块化和可维护性。

10、总结

关注点分离是软件设计中的一个关键原则,它通过将不同的功能和业务逻辑分离到不同的组件中,帮助我们构建更加清晰、灵活和易于维护的系统。虽然实现关注点分离可能需要更多的设计工作,但它为系统的可持续发展奠定了基础。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。