[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

相关文章

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

详解C#如何提取PDF文档中的图片

《详解C#如何提取PDF文档中的图片》提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使用,下面我们就来看看如何使用C#通过代码从PDF文档中提取图片吧... 当 PDF 文件中包含有价值的图片,如艺术画作、设计素材、报告图表等,提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

Python基于wxPython和FFmpeg开发一个视频标签工具

《Python基于wxPython和FFmpeg开发一个视频标签工具》在当今数字媒体时代,视频内容的管理和标记变得越来越重要,无论是研究人员需要对实验视频进行时间点标记,还是个人用户希望对家庭视频进行... 目录引言1. 应用概述2. 技术栈分析2.1 核心库和模块2.2 wxpython作为GUI选择的优

利用Python开发Markdown表格结构转换为Excel工具

《利用Python开发Markdown表格结构转换为Excel工具》在数据管理和文档编写过程中,我们经常使用Markdown来记录表格数据,但它没有Excel使用方便,所以本文将使用Python编写一... 目录1.完整代码2. 项目概述3. 代码解析3.1 依赖库3.2 GUI 设计3.3 解析 Mark

SpringBoot如何通过Map实现策略模式

《SpringBoot如何通过Map实现策略模式》策略模式是一种行为设计模式,它允许在运行时选择算法的行为,在Spring框架中,我们可以利用@Resource注解和Map集合来优雅地实现策略模式,这... 目录前言底层机制解析Spring的集合类型自动装配@Resource注解的行为实现原理使用直接使用M

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

Python实现合并与拆分多个PDF文档中的指定页

《Python实现合并与拆分多个PDF文档中的指定页》这篇文章主要为大家详细介绍了如何使用Python实现将多个PDF文档中的指定页合并生成新的PDF以及拆分PDF,感兴趣的小伙伴可以参考一下... 安装所需要的库pip install PyPDF2 -i https://pypi.tuna.tsingh

基于Python开发批量提取Excel图片的小工具

《基于Python开发批量提取Excel图片的小工具》这篇文章主要为大家详细介绍了如何使用Python中的openpyxl库开发一个小工具,可以实现批量提取Excel图片,有需要的小伙伴可以参考一下... 目前有一个需求,就是批量读取当前目录下所有文件夹里的Excel文件,去获取出Excel文件中的图片,并