[Chromium中文文档]跨平台开发的约定与模式

2024-06-08 18:18

本文主要是介绍[Chromium中文文档]跨平台开发的约定与模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

跨平台开发的约定与模式

转载请注明出处:https://ahangchen.gitbooks.io/chromium_doc_zh/content/zh//General_Architecture/Conventions_and_patterns_for_multi-platform_development.html

全书地址

Chromium中文文档 for https://www.chromium.org/developers/design-documents
持续更新ing,欢迎star
gitbook地址:https://ahangchen.gitbooks.io/chromium_doc_zh/content/zh//
github地址: https://github.com/ahangchen/Chromium_doc_zh

Chromium是一个巨大而复杂的跨平台产品。我们试图在不同平台间共享尽可能多的代码,同时为每个平台用最合适的方式实现UI和操作系统集成。这提供了一个更好的用户体验,但它给代码增加了额外的复杂度。这个文档描述了保持这种跨平台代码简洁性的推荐实践。

我们使用大量不同带后缀的文件来表示一个文件应该被使用的时机:

  • Mac文件中,低层级文件使用_mac后缀,Cocoa(Mac UI)文件使用_cocoa后缀。
  • iOS文件使用_ios后缀(尽快iOS使用一些特定的_mac文件)。
  • Linux文件中,低层级文件使用_linux后缀,GTK相关文件使用_gtk后缀,X Windows(不使用GTK)特定文件使用_x后缀。
  • Windows文件使用_win后缀。
  • Mac,iOS和Linux共享的Posix文件使用_posix后缀。
  • Chrome view UI相关布局系统文件(在Windows和实验室环境GTK上)使用_views后缀。

独立的浏览器后端文件放在他们自己的目录里:

  • Mac Cocoa: chrome/browser/ui/cocoa
  • Linux GTK: chrome/browser/ui/gtk
  • Windows Views (和实验室GTK-views): chrome/browser/ui/views

编码风格 页面列出一些风格上影响平台相关定义的规则。

如何隔离平台相关代码

小的平台差异: #ifdefs

当你有一个有着许多共享函数或数据成员和些许不同之处的类,在平台相关的部分使用#ifdefs。如果没有显著的差异,这会让每个人将每件事隔离开更加容易。

小的平台差异在头文件处理,大的差异在实现中处理:片段实现

可能有这样的情况,头文件几乎没有差别,部分实现有巨大的实现差异。例如base/waitable_event.h定义了一个通用的有着大量平台差异的API。

有着显著的实现差异,实现文件可以被隔离出来。这可以避免你陷入一个必须在include必要文件中为每个平台写一大堆#ifdef,并且使得追踪源码更容易(三个版本的函数集的代码放在同一个文件里可能令人困惑)。每个平台可以有不同的.cc文件,正如base/waitable_event_posix.cc中实现posix相关函数。如果在这个类里有跨平台的函数,他们应该被丢到一个名为base/waitable_event.cc的函数。

全平台实现和调用器:隔离实现

当抽象层面没有东西实现,就要在每个单独的文件里分别实现类。

如果所有的实现都在跨平台目录中,比如base,他们应该用平台的名字命名,比如base/foo_bar_win.h中的FooBarWin。这种例子通常很少,因为这些跨平台的文件通常设计用于跨平台代码,独立的头文件使得这种例子变得不可能。在一些地方,我们已经在不同的文件里定义了一个普通命名的类,所以PlatformDevice定义在skia/ext/platform_device_win.h, skia/ext/platform_device_linux.h, and skia/ext/platform_device_mac.h。如果你真的需要在跨平台代码里引用这个类,这是OK的。但通常,这种例子会变得遵循下面的这种规则。

如果实现存在于平台相关目录,比如chrome/browser/ui/cocoa或chrome/browser/ui/views,这个类就没有机会用于跨平台代码了。这种情况下,这个类和文件名应该忽略平台的名字,因为它是多余的。所以FooBar是在chrome/browser/ui/cocoa/foo_bar.h中实现的。

不要为每个平台创建不同的类,又把它们用typedef定义为同一个名字。我们曾经在PlatformCanvas上使用这种套路,根据平台,它被typedef为PlatformCanvasMac, PlatformCanvasLinux, 或 PlatformCanvasWin。这样就不可能提前声明这个类,而这是一个减小依赖的重要工具。

什么时候使用抽象的接口

通常,抽象接口与工厂不应该作为隔离平台差异的唯一目的。相反的,它应该用于将接口与优化代码设计的实现隔离开来。这最经常出现在从model中抽离view的实现中,比如TabContentsView或者RenderWidgetHostView。在这些例子里,model不依赖view的实现是有必要的。在许多情况下,多个平台的view只有一个实现,但为将来的开发提供了更干净的隔离与更多的可扩展性。

在有些地方,像TabContentsView,抽象层没有非抽象的、在平台间共享的函数。避免这种写法。如果不同view之间的代码总是一样,它可能首先就不应该在view中。

实现平台相关的UI

通常,从已有的平台相关的用户界面元素构建其他平台相关的用户界面元素。例如,view相关的类BrowserView负责构建许多浏览器对话框盒子。一种方法是,在一个平台无关的接口里包装UI元素,然后通过一个工厂,从一个model构造出它来。这是相当不必要的,因为它让迷乱了归属关系:大多数工厂构造的例子里,UI元素最后归属于创建它的model。然而在许多例子里,UI元素最容易由它所属的UI框架管理。例如,一个views::View归属于它的view层级,并且在包含它的window被销毁时,会自动被销毁。如果有一个对话框 views::View实现了一个平台无关的接口,然后被另一个对象拥有,那么views::View实例现在需要显式地告诉它的view层级不要去干涉它的生命周期。

e.g. 推荐这种写法:

// browser.cc:Browser::ExecuteCommand(..) {...case IDC_COMMAND_EDIT_FOO:window()->ShowFooDialog();break;...
}// browser_window.h:class BrowserWindow {
...virtual void ShowFooDialog() = 0;
...
};// browser_view.cc:BrowserView::ShowFooDialog() {views::Widget::CreateWindow(new FooDialogView)->Show();
}// foo_dialog_view.cc:// FooDialogView和FooDialogController在window被关闭的时候会被自动清理
class FooDialogView : public views::View {...private:scoped_ptr<FooDialogController> controller_; // 跨平台状态控制逻辑...
}

不推荐这种


// browser.cc:Browser::ExecuteCommand(..) {...case IDC_COMMAND_EDIT_FOO: {FooDialogController::instance()->ShowUI();break;}...
}// foo_dialog_controller.h:class FooDialog {public:static FooDialog* CreateFooDialog(FooDialogController* controller);virtual void Show() = 0;virtual void Bar() = 0;
};class FooDialogController {public:...static FooDialogController* instance() {static FooDialogController* instance = NULL;if (!instance)instance = Singleton<FooDialogController>::get();return instance;}...private:...void ShowUI() {if (!dialog_.get())dialog_.reset(FooDialog::CreateFooDialog(this));dialog_->Show();}// 为什么要把FooDialog或者甚至FooDialogController放在外面?// 大多数dialog起始很少被用到scoped_ptr<FooDialog> dialog_;
};// foo_dialog_win.cc:class FooDialogView : public views::View,public FooDialogController {public:...explicit FooDialogView(FooDialogController* controller) {set_parent_owned(false); // Now necessary due to scoped_ptr in FooDialogController.}...
};FooDialog* FooDialog::CreateFooDialog(FooDialogController* controller) {return new FooDialogView(controller);
}

有时候后一种模式是必要的,但这些情况很稀少,并且非常容易被前端的团队所理解。移植的时候,如果UI元素有时候像dialog box一样简单的话,考虑把后一种模式转为前一种。

这篇关于[Chromium中文文档]跨平台开发的约定与模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1042943

相关文章

一文详解Python如何开发游戏

《一文详解Python如何开发游戏》Python是一种非常流行的编程语言,也可以用来开发游戏模组,:本文主要介绍Python如何开发游戏的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、python简介二、Python 开发 2D 游戏的优劣势优势缺点三、Python 开发 3D

基于Python开发Windows自动更新控制工具

《基于Python开发Windows自动更新控制工具》在当今数字化时代,操作系统更新已成为计算机维护的重要组成部分,本文介绍一款基于Python和PyQt5的Windows自动更新控制工具,有需要的可... 目录设计原理与技术实现系统架构概述数学建模工具界面完整代码实现技术深度分析多层级控制理论服务层控制注

使用EasyPoi快速导出Word文档功能的实现步骤

《使用EasyPoi快速导出Word文档功能的实现步骤》EasyPoi是一个基于ApachePOI的开源Java工具库,旨在简化Excel和Word文档的操作,本文将详细介绍如何使用EasyPoi快速... 目录一、准备工作1、引入依赖二、准备好一个word模版文件三、编写导出方法的工具类四、在Export

利用Python操作Word文档页码的实际应用

《利用Python操作Word文档页码的实际应用》在撰写长篇文档时,经常需要将文档分成多个节,每个节都需要单独的页码,下面:本文主要介绍利用Python操作Word文档页码的相关资料,文中通过代码... 目录需求:文档详情:要求:该程序的功能是:总结需求:一次性处理24个文档的页码。文档详情:1、每个

C++读写word文档(.docx)DuckX库的使用详解

《C++读写word文档(.docx)DuckX库的使用详解》DuckX是C++库,用于创建/编辑.docx文件,支持读取文档、添加段落/片段、编辑表格,解决中文乱码需更改编码方案,进阶功能含文本替换... 目录一、基本用法1. 读取文档3. 添加段落4. 添加片段3. 编辑表格二、进阶用法1. 文本替换2

Java中的分布式系统开发基于 Zookeeper 与 Dubbo 的应用案例解析

《Java中的分布式系统开发基于Zookeeper与Dubbo的应用案例解析》本文将通过实际案例,带你走进基于Zookeeper与Dubbo的分布式系统开发,本文通过实例代码给大家介绍的非常详... 目录Java 中的分布式系统开发基于 Zookeeper 与 Dubbo 的应用案例一、分布式系统中的挑战二

Python实现自动化删除Word文档超链接的实用技巧

《Python实现自动化删除Word文档超链接的实用技巧》在日常工作中,我们经常需要处理各种Word文档,本文将深入探讨如何利用Python,特别是借助一个功能强大的库,高效移除Word文档中的超链接... 目录为什么需要移除Word文档超链接准备工作:环境搭建与库安装核心实现:使用python移除超链接的

基于Go语言开发一个 IP 归属地查询接口工具

《基于Go语言开发一个IP归属地查询接口工具》在日常开发中,IP地址归属地查询是一个常见需求,本文将带大家使用Go语言快速开发一个IP归属地查询接口服务,有需要的小伙伴可以了解下... 目录功能目标技术栈项目结构核心代码(main.go)使用方法扩展功能总结在日常开发中,IP 地址归属地查询是一个常见需求:

Python实现中文大写金额转阿拉伯数字

《Python实现中文大写金额转阿拉伯数字》在财务票据中,中文大写金额被广泛使用以防止篡改,但在数据处理时,我们需要将其转换为阿拉伯数字形式,下面我们就来看看如何使用Python实现这一转换吧... 目录一、核心思路拆解二、中文数字解析实现三、大单位分割策略四、元角分综合处理五、测试验证六、全部代码在财务票

基于 Cursor 开发 Spring Boot 项目详细攻略

《基于Cursor开发SpringBoot项目详细攻略》Cursor是集成GPT4、Claude3.5等LLM的VSCode类AI编程工具,支持SpringBoot项目开发全流程,涵盖环境配... 目录cursor是什么?基于 Cursor 开发 Spring Boot 项目完整指南1. 环境准备2. 创建