SCM软件配置管理

软件配置管理

软件配置管理 (Software Configuration Management, SCM)

问题引出

IEEE 定义

A discipline applying technical and administrative direction and surveillance to identify and document the functional and physical characteristics of a configuration item, control changes to those characteristics, record and report change processing and implementation status, and verify compliance with specified requirements.

一套应用技术上和管理上的指导和监督的方法,用来:识别和记录配置项的功能特征和物理特征;控制这些特征的变更;记录和报告变更的处理和执行的状态,以及验证起是否符合特定的需求。

有那么一类管理

软件配置管理,是关于软件资产的管理。

软件 = 源代码 + 文档。

源代码、设计文档、可以运行的程序等在软件研发过程中产生的有价值的东西,都是软件资产。

图书管理 VS 软件管理

  1. 图书管理的事图书资产,软件配置管理管理的是软件资产。其实这两种管的都是信息资产。
  2. 图书管理,需要把图书进行分类,以便检索;需要将图书存放在合适的地方,以便存取。还要防止虫吃鼠咬。软件配置管理也类似,需要把软件资产放在合适的目录结构里。防止丢失或者错乱。
  3. 在图书馆,要记录图书的借阅情况,为了保证图书不丢失;在软件配置管理中也类似,需要记录哪位程序员借出了哪个文件,什么时候还。如果程序员修改了它,还需要记录下来这些修改。
  4. 图书需要更新,软件也需要更新。

为什么是配置管理

  1. 汽车配置:底盘(传动系、转向系、制动系和行驶系)、发动机、车身、电气设备
  2. 电脑配置:主板(内存、CPU、显卡)、硬盘、机箱、显示器、外设
  3. 手机配置:屏幕、CPU、GPU、内存、闪存、主板、按键
  4. 软件配置:代码、文档、安装程序、引用类库、资源文件

从机器的视角,每个零件都有型号、编号。很容易想到,应该有某种列表或者文档来表明各个零部件型号和组成关系(Bill of Material, BOM)。当配置有变动的时候,要跟新这样的清单。而且这样的变动不能随随便便的,应该先让总工程师批准,做相应的测试。

从软件的视角,软件也是配置起来的。各个源文件、源代码和正确的文档搭配起来,编译产生正确的可以运行的程序。

另外软件配置管理更有自己的特点:

1.软件更容易发生变化,是向前演进的。

2.软件的相关性(耦合)更高,一旦需要改动,通常不是只更改一个文件。

其他的比喻

  • 结绳记事
  • 攀岩岩钉
  • 保险柜
  • 脚印
  • ……

最终定义

是一种应用于整个软件工程过程的标识、组织和控制修改的围绕软件资产的管理技术。

软件配置管理,又称软件形态管理、或软件建构管理,简称软件形管。界定软件的组成项目,对每个项目的变更进行管控(版本控制),并维护不同项目之间的版本关联,以使软件在开发过程中任一时间的内容都可以被追溯,包括某几个具有重要意义的数个组合。

在软件建立时变更是不可避免的,而变更加剧了项目中软件开发者之间的混乱。SCM活动的目标就是为了标识变更、控制变更、确保变更正确实现并向其他有关人员报告变更。从某种角度讲,SCM是一种标识、组织和控制修改的技术,目的是使错误降为最小并最有效地提高生产效率。

从流程角度看,软件配置管理是整个软件开发生命周期中一个非常核心的管理过程。配置管理实际贯穿了从需求分析、架构设计、项目管理、开发、集成构建、测试以及上线的全过程。这一过程不仅涉及宏观的项目进度控制、配置管理规范及计划、多地点开发规划等,也包括更细粒度的分支模型、构建及集成方式、变更处理流程,还包括微观的与开发人员直接相关的版本控制、差异比较和归并等。

Version Control-版本控制

Change Control-变更控制

Process Support-过程支持

关键活动包括:配置项、版本库管理、版本控制、变更控制、状态报告、配置审计等。

术语解释

配置

“配置”是在技术文档中明确说明并最终组成软件产品的功能或物理属性。因此“配置”包括了即将受控的所有产品特性,及其内容及相关文档,软件版本,变更文档,软件运行的支持数据,以及其他一切保证软件一致性的组成要素。

配置项

为了方便对“配置”进行管理,“配置”经常被划分为各类配置项,这类划分是进行软件配置管理的基础和前提。 配置项是一组软件功能或者物理属性的组合,在配置管理过程中,配置项被作为一个单一的实体对待。 一个系统包括的配置项的数目是一个与设计密切相关的问题。

  • 文档:一篇文档就是一个配置项
  • 代码:推荐将整个项目组的所有代码当做一个配置项。如果项目组内不同模块之间的进度相差很大的时候,将每一个模块的代码划分为一个配置项更加方便管理。

基线

在配置管理系统中,基线就是配置项在其生命周期的不同时间点上通过评审而进入正式受控的一种状态,而这个过程被称为“基线化”。

每一个基线都是其下一步开发的基准。

基线具有以下属性:

  • 通过正式的评审过程建立。
  • 基线存在于配置库中,基线的变更由变更控制委员会(CCB-Change Control Board)控制。
  • 基线是进一步开发和修改的基准。

版本

版本是表示一个配置项具有一组定义的功能的一种标识。随着功能的增加,修改或删除,配置项的版本随之演变。

版本以版本号进行标识。

  • 版本号 Version Number:为简略的表达特定版本的目的和意义,为方便区分不同的版本,我们需要版本号这个概念。又称作版本标识。
  • 版本库:也叫存储库,Repository。在版本库里,存储源代码的各个版本。当然存储的是不同版本见有差异的部分,增量存储。
  • 签入:检入,check in. 代码修改完了以后,需要告知版本控制工具,将新的代码保存到版本库中。
  • 签出:检出,chekc out。代码修改前,需要先告知版本控制工具,讲版本库中的代码复制到本地。

玄妙的学院派

配置计划

配置管理计划是开展所有配置管理活动的基础。

计划中应该明确以下要素:

  • 配置管理人员的组织和职责
  • 配置项的命名规则
  • 配置管理工具以及配置库结构
  • 标识的配置项和位置
  • 权限分配和管理方法
  • 配置库备份的周期、方法
  • 变更控制的流程和操作方法
  • 版本发布的计划和策略
  • 基线审计计划
  • 集成策略
  • 软件配置管理的场景

配置标识 Configuration Identification

是配置管理的一个组成部分,包括:选择产品的配置项、为他们制定唯一的标识,并在技术文档中记录其功能和屋里的特性。

配置标识是对软件配置进行管理的前提和基础。配置标识包括了软件配置项的选择、划分和对配置项的功能物理属性进行描述的过程。

每个配置项都必需被唯一地标识,这个唯一的标识被用于与其它配置项进行区分,跟踪和报告该配置项的状态。一般地,每个配置项被赋予一个标识符。

  • 文档:对所有文档而言,文件名就作为配置项的命名
  • 代码:使用“项目名-模块名+代码”或者“项目名+代码”的方式进行命名
  • 工具:以工具本身的名称命名

定义配置项的版本

单个配置项在每一次修改后都会发生变化,为了标识配置项在两次修改之间的不同,需要对配置项的版本进行标识。

配置项版本命名原则

配置项的版本标识建议采用的形式为:xx.yy的十进制标识符,其中xx起始为“1”,yy起始为“0”。

所有数字均是阿拉伯数字,并且单调递增。如果发生了重大的修改,xx递增;如果只有小修改,递增yy。

已基线化

成为基线的配置项是指已完成该配置项的审核、批准和签发并且成为创建或修改其他配置项的输入。

受管理和受控的

受管理和受控的配置项是指已提交审核,但还没有批准通过的配置项。

配置控制 Configuration Control

是配置管理的一个组成部分,包含评估、协调、批准/拒绝、实施对配置项的变更。

这发生在正式的配置标识之后。

配置控制包括配置项在完成基线化后所产生的变更的评估、协调、批准、驳回以及实现过程。

  • 变更请求的管理
  • 变更的协调工作

在项目开始时,由项目负责人根据项目的情况确定变更控制委员会(Change Control Board, CCB),并记录在配置管理计划中。CCB组长也可以根据更改请求的情况事件驱动地召集CCB会议。CCB也可以批量处理更改请求或采用定期的方式进行处理。

如有必要,可以设立不同级别的CCB,他们具有不同的授权,对不同层次的变更申请进行控制根据修改的影响范围,CCB召开相应的评估会议,并邀请相关人员参加

配置状态报告 Configuration Status Report

是配置管理的一个组成部分,记录和报告用来有效管理配置所需要的必要信息。这些信息包括一个已批准的配置标识清单,变更请求当前的处理状态,以及一品准的变更的实现情况。

配置状态报告是跟踪对软件的更改的过程,它保证对正在进行和已完成的变更进行记录、监视并通报给项目组和相关组成员。

一旦配置项基线化后,应该通知项目组, 内容应该包括基线化配置项的名称以及位置。另外应该周期或事件驱动地将更新后的培植状态发给项目组成员以及相关组,以确保配置项的状态能被相关人员所了解,根据需要一周或者两周发布一次

  • 版本库相关的信息:名字、存储位置、编号、管理员、主要用途描述
  • 版本库中产品的相关信息
  • 文件相关的信息
  • 变更请求、基线、发布、版本库的备份等

配置审计 Configuration Audit

执行审计以验证配置项符合特定的标准或需求

对配置管理的独立的查检过程,确认受控软件配置项满足需求并就绪。

  • 功能审计:配置项的变更控制是否和配置管理计划中的描述相一致
  • 物理审计:配置项的完整性、正确性, 一致性和可跟踪性

软件配置管理的组织

角色

  • 项目经理 PM: Project Manager
    • 制定和修改项目的组织结构和配置管理策略;
    • 批准、发布配置管理计划;
    • 决定项目起始基线和开发里程碑;
    • 接受并审阅配置控制委员会的报告。
  • 变更控制委员会 CCB: Change Control Board
    • 负责指导和控制配置管理的各项具体活动的进行,为项目经理的决策提供建议。其具体职责为以下几项:
      • 定制开发子系统;
      • 定制访问控制;
      • 制定常用策略;
      • 建立、更改基线的设置,审核变更申请;
      • 根据配置管理员的报告决定相应的对策。
  • 软件配置工程师 CMO: Configuration Management Officer
    • 根据配置管理计划执行各项管理任务,定期向CCB提交报告,并列席CCB的例会。其具体职责为以下几项:
      • 软件配置管理工具的日常管理与维护;
      • 提交配置管理计划;
      • 各配置项的管理与维护;
      • 执行版本控制和变更控制方案;
      • 完成配置审计并提交报告;
      • 对开发人员进行相关的培训;
      • 识别软件开发过程中存在的问题并拟就解决方案。
  • 系统集成工程师 SIO: System Integration Engineer
    • 系统集成员负责生成和管理项目的内部和外部发布版本,其具体职责为以下几项:
      • 集成修改;
      • 构建系统;
      • 完成对版本的日常维护;
      • 建立外部发布版本。
  • 软件开发工程师 DEV: Software Engineer
  • 软件测试工程师 QA: QA Engineer / Tester

制定配置管理流程

配置管理实施的一个重要阶段,主要目的是根据项目开发的需要,制定相应的配置管理流程,以更好地支持开发,主要活动包括:

  • 定制并行开发策略。合理的并行开发策略应该具有以下特点:协调项目的复杂性和需求,统一创建分支类型和元数据,为开发过程中的变更集成制定有效的规范,适时反映开发过程中方法和需求的变化。
  • 发布版本管理。软件开发过程中的一个关键活动是提取工件的相关版本,以形成软件系统的阶段版本或发布版本,一般将其称为稳定基线。一个稳定基线代表新开发活动的开始,而一系列定制良好的活动之后又会产生一个新的稳定基线。有效地利用此项功能,在项目开发过程中可以至始至终管理、跟踪部件版本间的关联。

软件配置管理 in CMMI

能力成熟度集成模型(Capability Maturity Model Integration, CMMI)是由美国卡耐基·梅隆大学的软件工程研究所组织开发,并于2002年发布的一种规范、实用的途径来管理软件过程的模型。CMMI通过指导软件开发人员的活动来改进软件过程,以达到软件过程可复用性、可定量管理、可有效控制的目的。

软件配置管理是CMMI可重复级的一个关键过程域(Key Process Area,KPA),其目的是在整个项目的软件生命周期中,保持软件产品的完整性和可追踪性,这包含了对改变的控制和所有能影响到改变的软件因素的管理。作为过程实现、过程优化的一部分,配置管理是实现软件过程的基本保证,它还是基于重用的软件开发的管理手段,所以成为软件过程管理的核心。CMMI模型清晰地描述了SCM,并说明了SCM 的目的和所要达到的目标,具体描述了某级成熟度下软件过程在该方面所应达到的一组目标和实现这些目标的一组关键实践(Key Pradice)。这些关键实践被划分为5类,分别为完成该组目标所需的承诺、执行能力、执行的活动、度量分析以及验证.使企业在实施软件配置管理时能知道到底要做什么,团队的配置管理现状如何评估,在哪些方面还可以进行改进等问题能得到具体的答案。

在CMMI中,对包括软件配置管理在内的配置管理工作,从如下角度进行了划分:

  • 建立基线

首先,识别配置项;接着,建立配置管理系统,用来存放配置项;最厚,通过评审或测试后,由配置项组成基线,作为未来开发的基础。

  • 建立并控制变更

要追踪变更请求,这包括新功能、功能增强,也包括缺陷。要评估它们,分配给合适的人去处理它们,还要检查以确保它们确实被处理了。要控制对配置项的变更,如果要改它,需要合适的人同意。改好后,要适当检查,才能入库。

  • 建立完整性

首先,要对配置管理活动做足够的记录。比如,对配置项的修订历史,对变更请求的状态转换过程,对不同基线的差异,等等;其次,要进行配置审计。确定配置项的内容是否合适,并出现在合适的地方,确定基线的内容正确。

  • 制度化已管理过程

在一个软件研发项目中做配置管理,首先要建立配置管理计划,然后确保有足够的资源,包括工具、环境,也包括人员。在配置管理系统运转过程中,要适当监控。

  • 制度化已定义过程

要形成可以指导现在和未来多个软件研发项目的配置管理过程规范。这样的规范不是一成不变的。要手机相关的信息、数据和反馈。并基于此进行软件配置管理的持续的改进。

配置管理的实践

  • 版本控制
    • 古老做法:文件夹目录共享,建立公共存储区
    • 现代做法一:文件加锁、修改、提交更新、解锁
    • 现代做法二:并行修改。由版本控制工具记录每个人修改前的版本和修改后的版本,然后再合并。
    • 即使只有一个程序员:程序员需要备份、回滚源代码、分支代码。
    • 多个程序员:多个程序员可能需要修改同一份源代码、需要等待测试团队的测试等。
    • 测试人员:需要统一需求文档、测试用例、测试计划等文档。
  • 代码构建
    • 构建:编译、链接和打安装包用来测试和发布的过程。
    • 及早和经常的集成,持续集成 Continuous Integration,必须充分借助于自动化工具的程度。
    • 构建的日志必须记录和保存
    • 每日构建:每天将最新的源代码进行编译,打包并通过冒烟测试。
  • 持续集成
    • 系统集成:简称集成,System Integration,其基本的使命,就是把产品的各个部分捏合在一起,并且保证产品作为整体是可以转的。并且运转没有问题。
    • 集成不一定发生在各个模块都开发完以后,而开始于设计阶段。
    • 作为改进,集成可以逐步进行。每完成一个模块,就加入到整体环境中来,发现问题并解决。
  • 并行开发
    • 版本标签:在当前分支通过标签的方式整体记录版本。
    • 版本分支:通过分支产生并行的版本进行新功能开发或者长期持续维护
    • 适当隔离与适当共享
  • 管理文档
    • 文档和源代码:源代码是人编写出来,给机器运行;文档是给人阅读。
    • 文档必须带有版本号和作者
    • 对修改有简单的描述,版本需要有最终状态
    • 趋势:Wiki 来源于夏威夷语(wee kee wee kee),中文是“快点快点”的意思。修改和展示都是基于网络的,在浏览器中完成。
  • 跟踪缺陷
    • 软件资产的改动会不可避免的产生缺陷,或者潜在的bug。
    • 通过缺陷跟踪系统,以及bug的状态转换,使得bug得以修复。
    • 分析统计缺陷相关数据,尤其注意漏测率。
  • 管理变更
    • 比缺陷更广阔的的话题,是变更请求。
    • 功能增强。
    • 在瀑布模型中管理变更

主流工具

  • Borland StarTeam

StarTeam是Borland公司的配置管理工具,是收费工具。

通过连接多个应用程序生命周期管理 (ALM) 库,优化您的软件开发生命周期 (SDLC)。通过跟踪对源代码、缺陷和功能的变更,获取对团队、项目和工具的控制。

StarTeam 的软件配置管理功能可用于在整个 软件开发生命周期SDLC 中管理和跟踪源代码变更,包括变更请求、缺陷、任务、需求用户案例和讨论。它提供了跨各种工具和存储库的更改。StarTeam 的软件配置管理功能同时适用于集中和异地软件开发团队,同时还可在您的所有软件资产中保持可见性和可追溯性,可用作您的单一事实来源。

  • IBM Rational ClearCase

Rational ClearCase 作为一款功能强大的软件配置管理( SCM )工具,在国内已经得到许多企业用户的认可并被广泛采纳。

IBM Rational ClearCase 通过自动化、集成和最佳经验简化了变更过程。ClearCase 帮助您更好地管理变更和资源,控制开发过程中发展演化的一切内容,包括需求、设计模型、源代码、变更请求以及测试脚本等。

  • VSS (Microsoft Visual SourceSafe)

VSS 的全称为 Visual SourceSafe 。作为 Microsoft Visual Studio 的一名成员,它主要任务就是负责项目文件的管理,几乎可以适用任何软件项目。管理软件开发中各个不同版本的源代码和文档,占用空间小并且方便各个版本代码和文档的获取,对开发小组中对源代码的访问进行有效的协调。

  • TFS (Microsoft Team Foundation Server)

    TFS作为VSS的替代者,具有十分强大的功能。

    1. 面向整个团队的协作工具

      Team Foundation Server 提供了一系列可与您的现有 IDE 或编辑器结合使用的协作工具,以便您的团队可以有效地处理各种形态和规模的软件项目。

    2. 面向敏捷团队的工具

      看板、Scrum、仪表板

      根据自身情况敏捷处理。通过积压工作和可自定义的看板,捕获和跟踪工作情况,并确定工作优先级。 工作项直接链接到代码以确保透明性,并可用于生成丰富的仪表板,方便您轻松生成报告。

    3. 持续集成

      生成、验证、部署

      使用持续集成 (CI) 生成尽早捕获质量问题,此类生成可以在代码发生变化后自动编译和测试您的应用程序。 使用持续交付自动部署应用程序或网站,这些应用程序或网站通过测试或对发布管道进行建模以匹配您现有的发布流程。

  • CVS (Concurrent Versions System)

CVS是一个C/S系统,是一个常用的代码版本控制软件。主要在开源软件管理中使用。与它相类似的代码版本控制软件有subversion。多个开发人员通过一个中心版本控制系统来记录文件版本,从而达到保证文件同步的目的。CVS版本控制系统是一种GNU软件包,主要用于在多人开发环境下的源码的维护

  • SVN (Subversion)

Subversion是一个自由,开源的版本控制系统。在Subversion管理下,文件和目录可以超越时空。Subversion将文件存放在中心版本库里。这个版本库很像一个普通的文件服务器,不同的是,它可以记录每一次文件和目录的修改情况。这样就可以籍此将数据恢复到以前的版本,并可以查看数据的更改细节。正因为如此,许多人将版本控制系统当作一种神奇的“时间机器”。

  • Git
    1. Git是一款免费、开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。
    2. Git的读音为/gɪt/。
    3. Git是一个开源的分布式版本控制系统,用以有效、高速的处理从很小到非常大的项目版本管理。
    4. Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

Torvalds 开始着手开发 Git 是为了作为一种过渡方案来替代 BitKeeper,后者之前一直是 Linux 内核开发人员在全球使用的主要源代码工具。开放源码社区中的有些人觉得 BitKeeper 的许可证并不适合开放源码社区的工作,因此 Torvalds 决定着手研究许可证更为灵活的版本控制系统。尽管最初 Git 的开发是为了辅助 Linux 内核开发的过程,但是我们已经发现在很多其他自由软件项目中也使用了 Git。

SVN的搭建和使用

SVN的搭建

Windows操作系统搭建,只需要安装VisualSVN server变完成了服务端的搭建。

  1. 下载VisualSVN Server (注意操作系统是32位或64位)
  2. 双击安装,全部默认并且下一步,最后选择“Standard Edition”(标准版)
  3. 安装完以后启动VisualSVN Server Manager
  4. 创建新的代码库, Create New Repository
  5. 创建新的用户, Create User, 基本的用户权限是读写权限。

客户端使用TortoiseSVN将文件签出进行使用。

  1. 下载TortoiseSVN
  2. 双击安装,全部下一步,直至完成。
  3. 在任意地方新建SVN文件夹,建议在D:\根目录
  4. 双击进入SVN文件夹,右键选择“TortoiseSVN”->"Repo-Browser" 或者 “SVN Checkout”
  5. 选择SVN COmmit提交。

SVN的使用

  • SVN Checkout
  • Add
  • Delete
  • Rename
  • Revert
  • Check for modifications
  • SVN Update
  • SVN Commit
  • Show log
  • Branch/tag
  • Get lock
  • Release lock
  • Clean up

SVN的高级实践

冲突的解决

分支的合并

SVN和Git

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容