Final Report

Final Report

15331033 陈文彬
简短的课程学习自我总结(400字以内)
  • 请不用讲述与分析、设计、开发、管理无关的话题
  • 可以包括对同学帮助的致谢(同学姓名请用 github 昵称表示,不许出现真实姓名)
  • 0 ~ 400字,即没有这段也没关系

通过课程学习,学会了对项目进行用例建模,领域建模,状态建模等,感觉把模型设计好还是很能帮助我们理清思路更好的进行迭代开发.
另外项目前期的需求分析真的很重要,好的需求分析能明确我们开发的目标和计划.
最后就是开发阶段,对于api的设计,小组中开发前后端的成员之间还是应该多讨论,明确api设计,对接阶段才能更流畅.

PSP 2.1 统计表
PSP2.1 Personal Software Process Stages Time(%)
Planning 计划 4
Estimate 估计这个任务需要多少时间 4
Development 开发 83
Analysis 市场调研,需求分析 20
Design Spec 生成设计文档 5
Design Review 设计复审 3
Coding Standard 代码规范 2
Design 具体设计 8
Coding 具体编码 30
Code Review 代码复审 5
Test 测试 10
Reporting 报告 15
Test Report 测试报告 5
Size MeaSurement 计算工作量 5
Postmortem&Process Improvement Plan 时候总结,并提出过程改进计划 5
个人分支的 GIT 统计报告(不需要解释原因)- 仅需要提交截图

dashboard
Alt text
backend
Alt text

自认为最得意/或有价值/或有苦劳的工作清单,含简短说明(一句话)

关于django的csrftoken检验

关于django的csrftoken检验

CSRF介绍

https://www.ibm.com/developerworks/cn/web/1102_niugang_csrf/index.html

项目中的csrf坑

用django自带的用户系统登录后会在cookie生成一个sessionid保持用户登录状态,同时生成一个csrftoken防止csrf攻击
由于有这个csrftoken的机制,前端登录后,想调用后端api或者通过sessionid认证用户信息时,有时候就会报错
CSRF Token missing or incorrect

解决办法

前端发送请求时在request添加头部
X-CSRFToken,值为cookie中的csrftoken
若后端csrftoken跳异常,可尝试

1
2
from django.template.context_processors import csrf
csrf(request)

网上也有说法可以用

1
@csrf_exempt

修饰报错的函数,忽略csrf
或者在settings.py中注释掉
‘django.middleware.csrf.CsrfViewMiddleware’,

django作为项目后台的docker-compose部署

django作为项目后台的docker-compose部署

准备

Linux下安装docker

1
2
sudo apt-get install docker
sudo apt-get install dock

Linux下安装docker-compose

1
2
$ sudo curl -L https://github.com/docker/compose/releases/download/1.17.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose

dockerfile编写
1
2
3
4
5
6
7
FROM python:3  #python 版本
ENV PYTHONUNBUFFERED 1 #环境变量
RUN mkdir /code #创建文件夹code
WORKDIR /code #设置工作目录
ADD requirements.txt /code/ #requirements.txt为项目额外需要的依赖包,将其添加到code文件夹
RUN pip install -r requirements.txt #code文件夹下运行pip install安装依赖包
ADD . /code/ #将当前目录文件添加到code文件夹
requirements.txt编写
1
2
3
4
Django>=2.0  #下载django对应版本
djangorestframework
dwebsocket
Pillow #需要的依赖包,前面三个是我项目需要的包,实际编写应根据自己项目需要的,写不全也不要紧,docker-compose build的时候会提示缺少什么包的
docker-compose.yml编写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
version: '3'  #版本

services: #各个服务
db: #数据库服务名
image: postgres #数据库镜像,根据需要可以选择sql,若是sqlite3则不用数据库镜像
web: #后端服务名
build: . #docker-compose build时在当前目录build
command: python3 manage.py runserver 0.0.0.0:8000 #docker-compose up时执行的命令
volumes:
- .:/code #路径映射
ports:
- "8000:8000" #端口映射
depends_on:
- db #服务依赖
Django默认数据库设置

修改settings.py中的数据库默认设置

1
2
3
4
5
6
7
8
9
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'postgres', #数据库
'USER': 'postgres',
'HOST': 'db', #主机名,即在docker-compose中的db服务
'PORT': 5432, #服务器端口
}
}

具体可参考
https://shenxgan.gitbooks.io/django/content/publish/2015-07-13-django-mysql.html
最终你的django项目里应该有

  • Dockerfile
  • requirements.txt
  • docker-compose.yml

处于同一目录下

后台部署

将项目文件夹拷贝到服务器上,进入项目文件夹,执行
sudo docker-compose up
即构建并启动项目
sudo docker-compose build
为构建项目
sudo docker-compose restart
为重启项目

紧张刺激的掉坑环节

sudo docker-compose up的时候可能会报错

1
ERROR: Couldn't connect to Docker daemon at http+docker://localunixsocket - is it running?

这个报错应该是跟docker和docker-compose是否以管理员权限开启有关,遇到报错可以尝试
先关掉docker,管理员权限,非管理员权限和系统的docker
service docker stop
sudo service docker stop
systemctl stop docker
再以管理员权限重启或开启docker
sudo service docker start/restart
sudo systemctl start docker
sudo systemctl restart docker
最后
sudo docker-compose up
应该就可以了

Lesson16_Homework

Lesson16_Homework

使用 ECB 实现 make reservation 用例的详细设计(包含用例简介,顺序图,类图)
用例简介
  • 用户登录
  • 根据位置,日期搜索酒店
  • 选择酒店
  • 选择房间,填写房间信息
  • 提交订单
  • 填写银行卡信息
  • 支付订单
    顺序图
    Alt text
    类图
    Alt text
    将逻辑设计类图映射到实际项目框架的包图。用树形结构表述实现的包和类
    Alt text
    树形结构
    Alt text

Lesson13_Homework

Lesson13_Homework

描述软件架构与框架之间的区别与联系

框架不是构架(即软件体系机构)。体系结构确定了系统整体结构、层次划分,不同部分之间的协作等设计考虑。框架比架构更具体。更偏重于技术涉嫌。确定框架后,软件体系结构也随之确定,而对于同一软件体系结构(比如Web开发中的MVC),可以通过多种框架来实现。

以你的项目为案例
  • 绘制三层架构模型图,细致到分区
    Alt text
  • 结合你程序的结构,从程序员角度说明三层架构给开发者带来的便利

三层架构是指:视图层View、服务层Service、持久层Dao,分别完成不同的功能。

View层:用于接收用户提交请求的代码在这里编写。
Service层:系统的业务逻辑主要在这里编写。
Dao层:直接操作数据库的代码在这里编写。

为了更好的降低各层间的耦合度,在三层架构程序设计中,采用面向抽象编程。即上层对下层的调用,是通过接口实现的。而下层对上层的真正服务提供者,是下层接口的实现类。服务标准(接口)是相同的,服务提供者(实现类)可以更换。这就实现了层间的耦合。

三层架构的优点如下:
1.分离开发人员的关注。由于某一层仅仅调用其相邻下一层所提供的服务,所以,只要本层的API和相邻下一层的API定义完整,开发人员在开发某一层时就可以像关注集中于这一层所用的思想、模式、技术,这样,就等同于将分工带来的生产力提高优势引入软件开发。
2.无损替换
3.降低了系统间的依赖
4.复用

研究 VUE 与 Flux 状态管理的异同

flux:
状态集管理框架,由facebook创建,专门用来构建前端框架结构的框架,便于维护,用于安全考虑
它分为四层:view视图层, action层, dispatcher派发层, store仓库层
view——>action——>dispatcher——>store返回——>dispatcher——>view(接收的方法:register())
vue:
1、vuex是专门为vue提供的状态管理工具
2、便于维护,保证安全,vue中引入vuex,解决状态之间共享的问题
3、多个组件调用一个状态,将原来组建与组件之间的状态传递改成组件与仓库之间的传递
4、vuex适用于构建大型的项目,如果不是大型项目,使用vuex会使代码更加繁琐
5、vuex核心:
state:存放多个组件共享的状态(数据)
mutations:存放更改state里状态的方法,用于变更状态,是唯一一个更改状态的属性
getters:将state中某个状态进行过滤,然后获取新的状态,类似于vue中的computed
actions:用于调用事件动作,并传递给mutation
modules:主要用来拆分state
vueComnent——>(dispatch)Action——>(commit)——>Mutations——>(mutate)State——>(render)VueComponent

Lesson9_Homework

Lesson9_Homework

建模练习
练习文档编写
  • 选择一个你喜欢的 移动App 或 其中某业务
  • 参考 Asg_RH 文档格式 编写软件描述
  • 文档要包含一个业务的完整过程

美团外卖的点餐业务
软件描述:
1.填写搜索信息,搜索商家或商品名称,就可以得到软件筛选出来的商家
Alt text
2.在商家列表中根据爱好选择商家
Alt text
3.根据需要增、删、查看菜品,确定菜品后点去结算
Alt text
4.填写配送信息,包括配送地址、配送时间,可选择使用红包,同时可以确认订单信息,包括价格,菜品信息,优惠等
Alt text
5.提交订单并支付
Alt text

建模
  • 用例图
    Alt text
  • 用户点餐活动图
    Alt text
  • 点餐业务领域模型
    Alt text
  • 用户点餐状态图
    Alt text
  • 支付订单场景的系统顺序图与操作协议
    Alt text

Lesson8_Homework

Lesson8_Homework

1)使用 UML State Model
  • 建模对象: 参考 Asg_RH 文档, 对 Reservation/Order 对象建模。
  • 建模要求: 参考练习不能提供足够信息帮助你对订单对象建模,请参考现在 定旅馆 的旅游网站,尽可能分析围绕订单发生的各种情况,直到订单通过销售事件(柜台销售)结束订单。
    Alt text
    2)研究淘宝退货流程活动图,对退货业务对象状态建模
    Alt text

Lesson7_Homework

Lesson7_Homework

领域建模
a.阅读 Asg_RH 文档,按用例构建领域模型。
  • 按 Task2 要求,请使用工具 UMLet,截图格式务必是 png 并控制尺寸
  • 说明:请不要受 PCMEF 层次结构影响。你需要识别实体(E)和 中介实体(M,也称状态实体)
    • 在单页面应用(如 vue)中,E 一般与数据库构建有关, M 一般与 store 模式 有关
    • 在 java web 应用中,E 一般与数据库构建有关, M 一般与 session 有关
      Alt text
      b.数据库建模(E-R模型)
  • 按 Task 3 要求,给出系统的 E-R 模型(数据逻辑模型)
  • 建模工具 PowerDesigner(简称PD) 或开源工具 OpenSystemArchitect
  • 不负责的链接 http://www.cnblogs.com/mcgrady/archive/2013/05/25/3098588.html
    Alt text

  • 导出 Mysql 物理数据库的脚本

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    CREATE TABLE `Traveller`
    (
    userid INTEGER NOT NULL,
    name VARCHAR(30) NOT NULL,
    email VARCHAR(30),
    PRIMARY KEY (userid)
    );

    CREATE TABLE `Hotel`
    (
    Hotelid INTEGER NOT NULL,
    HotelName VARCHAR(30) NOT NULL,
    City VARCHAR(30) NOT NULL,
    lowestP INTEGER,
    PRIMARY KEY (Hotelid)
    );

    CREATE TABLE `Room`
    (
    roomid INTEGER NOT NULL,
    adultsNum INTEGER NOT NULL,
    childrenNum INTEGER NOT NULL,
    roomType VARCHAR(30) NOT NULL,
    Hotelid INTEGER NOT NULL,
    PRIMARY KEY (roomid,Hotelid)
    );

    CREATE TABLE `Reservation`
    (
    reservationid INTEGER NOT NULL,
    checkinDate DATE NOT NULL,
    checkoutDate DATE NOT NULL,
    price INTEGER NOT NULL,
    userid INTEGER NOT NULL,
    Hotelid INTEGER NOT NULL,
    roomid INTEGER NOT NULL,
    PRIMARY KEY (reservationid)
    );

    CREATE INDEX idxReservation1 ON Reservation
    (
    userid
    );

    CREATE TABLE `CreditCard`
    (
    cardid INTEGER NOT NULL,
    cardNumber VARCHAR(30) NOT NULL,
    cardHolderAddress VARCHAR(30),
    userid INTEGER NOT NULL,
    PRIMARY KEY (cardid)
    );

    CREATE INDEX idxCreditCard1 ON CreditCard
    (
    userid
    );
  • 简单叙说 数据库逻辑模型 与 领域模型 的异同
    领域模型的内容包括重要的 实体及实体之间的关系 。在概念数据模型中 不包括实体的属性 ,也 不用定义实体的主键
    逻辑模型既要面向用户,又要面向系统 。逻辑数据模型 反映的是系统分析设计人员对数据存储的观点,是对概念数据模型进一步的分解和细化。内容包括所有的实体和关系,确定每个实体的属性,定义每个实体的主键,指定实体的外键,需要进行范式化处理。
    两种模型都需要满足用户的需求,确定实体jian

LeetCode_8_String_to_Integer(atoi)

LeetCode_8_String_to_Integer(atoi)

问题描述

Implement atoi which converts a string to an integer.

The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.

The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.

If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.

If no valid conversion could be performed, a zero value is returned.

Note:
Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. If the numerical value is out of the range of representable values, INT_MAX (2^31 − 1) or INT_MIN (−2^31) is returned.
简单的说就是把一个string转为int

样例

Alt text

代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
public:
int myAtoi(string str) {
long long re = 0;
int len = str.length();
int i, j;
i = 0;
int fu = 1;
//排除一开始的空字符
while(str[i] == ' ') i++;
//判定符号和非法字符串
if(str[i] == '-') {
fu = -1, i++;
}
else if(str[i] == '+') {
fu = 1, i++;
}
else if(str[i] < '0' || str[i] > '9') return 0;
//cout << i << endl;
//遍历求值
for(; i < len; i++) {
//若为数字,求和,否则返回当前值
if(str[i] >= '0' && str[i] <= '9') {
re = re * 10 + str[i]-'0';
//判断边界
if(re*fu < pow(-2,31)) return pow(-2,31);
else if(re*fu > pow(2,31)-1) return pow(2,31)-1;
} else return re*fu;
}
return re*fu;
}
};

LeetCode_6_ZigZag Conversion

LeetCode 6.ZigZag Conversion

问题描述:

The string “PAYPALISHIRING” is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
Alt text

And then read line by line: “PAHNAPLSIIGYIR”

Write the code that will take a string and make this conversion given a number of rows:

1
string convert(string s, int numRows);

样例如下

Example 1:

1
2
Input: s = "PAYPALISHIRING", numRows = 3
Output: "PAHNAPLSIIGYIR"

Example 2:

1
2
Input: s = "PAYPALISHIRING", numRows = 4
Output: "PINALSIGYAHRPI"

Explanation:
Alt text

解题思路:

弄一个numRows * s.length()的数组,便利s,按规律插入就行了

代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Solution {
public:
string convert(string s, int numRows) {
int len = s.length();
vector<vector<char> > ss(numRows,vector<char>(len, '0'));
int i, j;
if(len == 0) return "";
if(numRows == 1) return s;
ss[0][0] = s[0];
int count = 0;
bool spe = false;
int x = 0;
int y = 0;
for(i = 1; i < len; i++) {
if(!spe) {
x++;
ss[x][y] = s[i];
//cout << x << " " << y << " " << ss[x][y] << endl;
} else {
x--, y++;
ss[x][y] = s[i];
//cout << x << " " << y <<" " << ss[x][y] << endl;
}
count++;
if(count == numRows-1) {
count = 0;
spe = !spe;
}
}
string re;
for(i = 0; i < numRows; i++) {
for(j = 0; j <= y; j++) {
if(ss[i][j] != '0') re.push_back(ss[i][j]);
//cout << ss[i][j ] << endl;
}
}
return re;
}
};