基础配置
SSH 配置
针对 SSH 连接进行一些特殊的配置,防止外部暴力破解等。
http://blog.etby.org/2019/11/21/linux-secure-ssh/
防火墙配置
待续……
格物、致知、诚意、正心
beancount 是一种复式记账的语言,可以将交易记录在文本文件中,可以做很多的脚本处理,还有 Web 界面可以查看账目。
基于会计恒等式产生的记账形式,每笔交易的结果至少被记录在一个借方和一个贷方的账户,且该笔交易的借贷双方总额相等,即 ”有借必有贷,借贷必相等“ 。
资产 = 负债 + 所有者权益
资产 = 负债 + 所有者权益 + (收入 - 费用)
复式记账可以做到对资金的强掌控,每一笔资金的来源和去向一清二楚。
1 | # 本文所有 python 环境都是 python3 |
安装完成即可开始记账,如何记账可以参考文章最下面的几篇博客。
我是用 Docker 部署 fava 来使用的,一般小笔的交易直接在 fava 的编辑器中打开账本进行记账。
1 | # 进入账本文件夹中执行 |
1 | # 进入 venv |
创建 Dockerfile 文件,然后输入以下内容
1 | FROM python |
创建 docker-compose.yml 文件,输入以下内容(具体配置可按自己的需求改变)
1 | version: "3.3" |
注意:
1 | docker-compose up -d --buil |
之后可以访问: http://localhost:8888/ 查看账本是否部署成功
1 | /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" |
1 | brew cask install iterm2 |
1 | sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" |
1 | brew cask install google-chrome |
1 | brew cask install dropbox |
1 | brew cask install alfred |
1 | brew cask install 1password |
1 | brew cask install joplin |
1 | brew cask install typora |
1 | brew cask install telegram-desktop |
1 | brew cask install visual-studio-code |
1 | brew cask install jetbrains-toolbox |
1 | brew cask install docker |
1 | brew install ansible |
1 | brew install git-flow-avh |
1 | brew install nvm |
1 | npm install -g hexo-cli |
ubuntu 直接使用包管理器安装,其他平台类似。
1 | apt install nfs-kernel-server |
创建专用目录。
1 | mkdir -p /data/nas-root |
导出文件配置
1 | vim /etc/exports |
使配置生效
1 | exportfs -a |
查看服务器共享文件状态
1 | showmount -e 10.10.10.100 |
我这边是在 Mac 下挂载,Linux 平台只需要改变路径就好。
1 | sudo mount -o resvport -t nfs 10.10.10.100:/data/nas-root /Volumes/NAS |
Ubuntu 使用包管理器安装
1 | apt install samba |
增加 SAMBA 账户
1 | smbpasswd -a etby |
编辑配置文件
1 | vi /etc/samba/smb.conf |
每次Linux
初始化配置都比较麻烦,所以在此记录一下,以后方便配置。我主要是用 Ubuntu
,所以以下是基于它的,其他系统类似。
1 | sudo vi /etc/sudoers |
针对主要用来做母鸡的服务器
1 | sudo apt autoremove --purge snapd |
OH MY ZSH
以及它的工具链用的很熟练了,感觉非常舒服。
1 | # 安装本体 |
1 | plugins=( |
1 | # 添加驱动仓库 |
最近,正在做一个新需求:需要在已有的页面中新增一种与当前数据结构完全不同的数据展示,页面展示基本不变,但后端返回数据结构与这个数据代表的意义完全不同。在产品与UI眼中,这或许并不是什么大的变动,但对程序来说却比较复杂,所有牵扯到的逻辑都需要梳理。(这或许也是产品和研发打架的原因之一)
一般小型项目都是 接口 -> 数据库 -> 界面展示
一把梭,只用一个类来定义对象,中间不会经过任何转化和分层。一般来说数据结构很少变,而且多数据类型同一个页面展示的情况大多比较稀少,所以一般都是如此处理的。
我这边一般想到几个方法:
这样一般改变逻辑较多,牵扯到逻辑判断的地方都要增加新数据结构的处理。
在已有对象中创建一个字段,将新对象注入,改写 get
类型方法,返回新对象的数据,展示到页面上。
这样改动比较简单,但容易发生数据访问问题,需要多测试才行。而且侵入性太强,需要更改已有数据结构,导致逻辑混乱。
这种方法只适用于整体数据结构改变的方式,如果是局部异同,则无法解决。而且会增加界面,增加逻辑复杂度,如果界面逻辑更改,则需要两处都进行更改。
具体操作其实和直接更改类似,都是需要同样的工作量。而且由于增加了许多兼容性的处理,会导致工作量更大。
好处是,兼容性足够强,再次增加逻辑方便,而且抽象提好了数据层次,对数据结构侵入性没有。
坏处是,之前所有逻辑都需要更改数据结构,添加此层次。
这种方法一般是最容易实现的,但是如果需要进行空字段的处理,同样会增加工作量,比较麻烦。在整体逻辑需要用到某些数据的时候,如果没有此数据,则需要增加专用的处理逻辑。如果需要更改的地方比较少,工作量不太的话,此种方法则是一般情况下大多数人会选择的,但是会导致一些认知混乱,当然如果逻辑本身不复杂的话,一般不会出问题。
https://github.com/etby/DataCache
这是一个对象缓存框架,按理说应该是一个对象池。
http://blog.etby.org/2018/03/27/datacache-library/
这是我在写发布这个库的第一个版本之后,写的一篇简单介绍的博客。
在做一个应用的时候,经常会遇到各种页面之间数据同步的问题。这个基本是每个APP开发工程中都会遇到的问题,解决方式也是各式各样。
在这里说一下我的方法:
DataBinding
set
方法进行设置,UI 就会自动更新以上是核心逻辑,在整个应用中保持单个数据只使用一个Java
对象,然后使用DataBinding
框架触发界面更新。( 现在则可以增加LiveData
,使整个过程更流畅)
这个方式并不优美,但是挺好用的。对于掌控整个数据流来说,只需要掌控入口,工作量会小很多。
Gson
源码来做到自动解析的。领域驱动设计虽然之前自己查了很多资料,也看了一些书,但始终不得要领,而且无法进行实际的运用。毕竟增加了许多工作量,我却无法灵活使用,不熟的东西还是不适合使用。
处理上面提到的增加页面数据的问题时,我想到了 DataCache
库,想到了它的优缺点和我现在的窘境,之后想到的 DDD
的分层。对数据结构的分层:VO/PO/DTO
等等。
虽然 DDD 比较庞大,但其实我们已经有意无意的使用了类似的思想。比如上面页面问题提出公共数据对象的方式,或者聚合数据对象的方式,都是表现层分层的一种思想,那些对象已经类似VO
了。
我们则可以做的更好,将VO
完全独立出来,然后使用DataCache
将VO
单例化。这样就可以解决多页面的数据同步问题,在逻辑需要用到数据的时候则可以使用真实数据对象来进行操作。这样就可以避开单对象的循环引用的问题,序列化和传递对象则不必太拘束。
逻辑层和展现层使用完全不同的数据结构,当逻辑改变时,则就不需要进行大量的更改,只需要在层与层之间进行一些转化。或许这样做之后,增加的学习成本和工作量则不再是阻碍了。
这两天由于公司移动方向的开发资源不足,所以决定接触一下一些跨平台的方案。由于Flutter
暂时还没有 Release ,所以主要还是先依靠 React Native
来做一些页面。虽然 React Native
已经是非常成熟的技术了,但我第一次用还是遇到了问题,在此记录一下。
因为 React Native
并不是完全脱离本地代码,而且也是集成进现有的项目,所以调用本地代码的需求比较大。需要在 iOS
和 Android
两方代码中都建立通道,才能在 React Native
中统一调用。
https://reactnative.cn/docs/native-modules-ios/
https://reactnative.cn/docs/native-modules-android/
上面是 React Native 中文网的两个文档,iOS 端直接按照文档步骤添加完成就好,Android 则与文档之中的不同。
1 | @ReactModule(name = "RNToast") |
与文档中不同的是增加了ReactModule的注解,主要参考了已有的 ToastAndroid 模块
1 | @ReactModuleList(nativeModules = { |
同样增加了 ReactModuleList 注解,以及使用了 LazyReactPackage 构建懒加载的 Package,主要参考了 MainReactPackage
1 | mReactInstanceManager = ReactInstanceManager.builder() |
这块是初始化 ReactRootView 时的参数设置,只需要增加自定义的 Package。预先提供的内置 Module 都是这样提供的,必要时可以通过 MainPeactPackage 进入之后查看源码
文档写了需要放在指定的包名的 MainApplication 中,这个并不需要。只需要在 ReactInstanceManager
构建时增加自定义的 Package
就好。
这个 package 需要在
MainApplication.java
文件的getPackages
方法中提供。这个文件位于你的 react-native 应用文件夹的 android 目录中。具体路径是:android/app/src/main/java/com/your-app-name/MainApplication.java
最近在用Flutter开发一个小一点的应用,有一些需要用到第三方框架的地方。但是当我按照文档接入之后,却出现了不该出现的问题。
在使用Fluro框架和Flutter_Redux框架的时候,存储在组件列表中的数据存储对象却无法找到。但是,越过App层的Fluro直接使用redux却可用。
在这还得吐槽一下Flutter,由于基础设施不完善,DEBUG起来非常麻烦,我也只能去求助大牛了。
初步怀疑是flutter_redux框架的bug,然后就提了一个issue。具体:
https://github.com/brianegan/flutter_redux/issues/41
之后大牛回复我希望能提供一个demo,我就建了一个项目,按照错误代码去重建。结果无论如何都无法重现,但是我又不能将旧代码逻辑转移过来,这样也许会再次产生,比较产生bug的因素目前还不明确。
我就只能将私有仓库公开,之后提交给大牛,让他帮我看看了。
没想到大牛直接给我提了一个 pull request,感谢大牛。
大牛给我的回答如下:
Hey there! The problem you’re experiencing is a confusing issue with how Dart handles imports. By changing the imports to package-relative paths, I was able to get the app working.
General rule: always use import ‘package:bungami_list:path/to/file rather than import ‘path/to/file.dart
This is definitely a confusing part of Dart, and it might be helpful to read this thread on more info: dart-lang/sdk#32042 (comment)
大体是说,是因为import包的问题:dart针对于URI不同的库就算代码相同,也不会认为是同一个库。所有尽量使用import全路径的方式来进行导包,就算是在同一个项目中。更多的信息可以看这里:https://github.com/dart-lang/sdk/issues/32042#issuecomment-363107221
经过这次的问题解决,我也获得了很多经验:
这个库会针对某一个特定的数据在内存中只保存一个对象,有数据更新的时候只会更新其中的字段,对象的引用并不会发生变化。
搭配数据绑定框架之后,可以保证所有页面的数据和状态同步。
数据同步其实一直是一个比较棘手的问题:当你在一个子页面点赞或者评论之后返回,父页面并没有发生变化,就比较尴尬了。如果嵌套更深的话,直接路由到首页也会出现这个问题。
这个在网页到还不是什么大问题,因为是不同的页面。但是在客户端的话,用户只会看到你这出问题了。
当然,解决方案也是有很多:
因为数据绑定我用的非常的多,而且同事们大家都觉得数据绑定框架不错,所以准备找一个依据此框的解决方案。而且我们一致认为不应该引入重量级的数据库来做这个事情,就只能在内存中做了。而且又因为状态改变之后需要同步到View,而数据绑定到布局的对象并不方便随便更改,所有就想到了在内存中维护一个唯一对象的方式。
最早虽然是唯一对象,但是并没有使用注解处理器生成代码,而是手动根据需要更新的字段进行配置。然后手动在API层做一些标记,但是这样比较麻烦,而且数据结构改变之后并不能及时同步,容易出现问题。
然后我就使用了注解处理器,根据API返回的字段进行标记。对内存中的原始对象只更新有用的字段,而且由于字段自动化了,工作量大大降低了。
注解处理器其实和代码并没有什么不同,不过就是在解决某些问题上效率有区别,在合适的场景选择合适的工具。
当然,要根据API返回数据进行标记的话,需要在JSON层面进行处理,所以就只能魔改Gson了。然后这两个库搭配起来,就做到了新流入的数据都是有标记的,对象中的哪些字段是有用的,都可以区分。
之后在数据层的接口处进行过滤,将新的解析出来的对象替换为原始对象,然后将需要更新的字段进行更新。这样,之前绑定的UI就会自动更新了。所有页面的数据永远都是最新的,永远都是相同的展示。
只建议没有能力或者没有资源做到完美的团队使用。
对于对数据流控制完美,逻辑架构优秀,开发资源充沛,排期并不紧张,测试严禁充分的优秀团队来说:这并不算是一个比较好的解决方案。
应该就到此为止了,整体设计思路已经完成,没有必要再增加新的功能,估计后续只是优化细节。
如果有一些优化或者扩展的想法,请联系我。
这算是我第一个正式的开源库了,很有纪念意义。
当然肯定不会是最后一个。我要渐渐成长,然后为开源做出更大的贡献~
服务器在阿里云香港, 避免不必要的网络问题. 使用Ubuntu系统, 因为包管理比较方便. 系统版本是Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-49-generic x86_64)
下面是一段在Ubuntu中安装Docker的脚步, 虽然我只在17.04
版本上测试过, 但是其他版本应该也可以用.
1 | #!/bin/bash |
如果不能使用, 请按照官网步骤进行. 如果是其他系统, 请参考官网其他系统的文档
https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/
如果Docker已经安装成功, 则只需要一行命令即可
docker run -d -p 127.0.0.1:8081:8081 --name nexus sonatype/nexus3
我这边需要使用Nginx反向代理, 所以直接本地访问, 如果想通过IP访问, 去掉IP配置即可
安装完成之后docker ps
查看一下, 应该会是下面这样
1 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES |
这样就已经启动了, 之后再用Nginx配置域名之后反向代理就可以通过域名访问了.
以上这个是我的jcenter的配置, 其他仓库配置都是一样, 只需要替换名称和远程连接就行
这是目前的配置, 代理了jcenter和mavenCentral, 还有google和jitpack.
然后创建了一个组, etby_works
. 这样我在studio客户端只需要配置一个就好, 在需要的时候可以直接在服务器上新增远程仓库. 新项目可以继续创建新的组, 也可以使用一个大组来负责所有的远程仓库.
Security -> Anonymous -> 取消勾选 Allow anonymous users to access the server 之后确认
创建用户时, 配置Save
按钮上方的 Granted
为nx-anonymous
, 此权限默认只读.
1 | allprojects { |
在Android Studio中配置成这样基本就没问题了, url
和账号密码都改成自己的, 上面的也不是我的账号密码 =-=
目前暂时没有仓库上传需求, 所以没有写上传的一些东西, 如果以后有机会再补全吧~
如果有不详细的地方, 可以直接Google, 也可以联系我.
纪念第一篇原创文章