[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

相关文章

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

Python操作PDF文档的主流库使用指南

《Python操作PDF文档的主流库使用指南》PDF因其跨平台、格式固定的特性成为文档交换的标准,然而,由于其复杂的内部结构,程序化操作PDF一直是个挑战,本文主要为大家整理了Python操作PD... 目录一、 基础操作1.PyPDF2 (及其继任者 pypdf)2.PyMuPDF / fitz3.Fre

PyQt5 GUI 开发的基础知识

《PyQt5GUI开发的基础知识》Qt是一个跨平台的C++图形用户界面开发框架,支持GUI和非GUI程序开发,本文介绍了使用PyQt5进行界面开发的基础知识,包括创建简单窗口、常用控件、窗口属性设... 目录简介第一个PyQt程序最常用的三个功能模块控件QPushButton(按钮)控件QLable(纯文本

SQL Server安装时候没有中文选项的解决方法

《SQLServer安装时候没有中文选项的解决方法》用户安装SQLServer时界面全英文,无中文选项,通过修改安装设置中的国家或地区为中文中国,重启安装程序后界面恢复中文,解决了问题,对SQLSe... 你是不是在安装SQL Server时候发现安装界面和别人不同,并且无论如何都没有中文选项?这个问题也

springboot自定义注解RateLimiter限流注解技术文档详解

《springboot自定义注解RateLimiter限流注解技术文档详解》文章介绍了限流技术的概念、作用及实现方式,通过SpringAOP拦截方法、缓存存储计数器,结合注解、枚举、异常类等核心组件,... 目录什么是限流系统架构核心组件详解1. 限流注解 (@RateLimiter)2. 限流类型枚举 (

C#监听txt文档获取新数据方式

《C#监听txt文档获取新数据方式》文章介绍通过监听txt文件获取最新数据,并实现开机自启动、禁用窗口关闭按钮、阻止Ctrl+C中断及防止程序退出等功能,代码整合于主函数中,供参考学习... 目录前言一、监听txt文档增加数据二、其他功能1. 设置开机自启动2. 禁止控制台窗口关闭按钮3. 阻止Ctrl +

Python实现中文文本处理与分析程序的示例详解

《Python实现中文文本处理与分析程序的示例详解》在当今信息爆炸的时代,文本数据的处理与分析成为了数据科学领域的重要课题,本文将使用Python开发一款基于Python的中文文本处理与分析程序,希望... 目录一、程序概述二、主要功能解析2.1 文件操作2.2 基础分析2.3 高级分析2.4 可视化2.5

基于Python开发一个图像水印批量添加工具

《基于Python开发一个图像水印批量添加工具》在当今数字化内容爆炸式增长的时代,图像版权保护已成为创作者和企业的核心需求,本方案将详细介绍一个基于PythonPIL库的工业级图像水印解决方案,有需要... 目录一、系统架构设计1.1 整体处理流程1.2 类结构设计(扩展版本)二、核心算法深入解析2.1 自

Java docx4j高效处理Word文档的实战指南

《Javadocx4j高效处理Word文档的实战指南》对于需要在Java应用程序中生成、修改或处理Word文档的开发者来说,docx4j是一个强大而专业的选择,下面我们就来看看docx4j的具体使用... 目录引言一、环境准备与基础配置1.1 Maven依赖配置1.2 初始化测试类二、增强版文档操作示例2.

C++ Log4cpp跨平台日志库的使用小结

《C++Log4cpp跨平台日志库的使用小结》Log4cpp是c++类库,本文详细介绍了C++日志库log4cpp的使用方法,及设置日志输出格式和优先级,具有一定的参考价值,感兴趣的可以了解一下... 目录一、介绍1. log4cpp的日志方式2.设置日志输出的格式3. 设置日志的输出优先级二、Window