当前位置: 首页 > news >正文

网站开发 移民站长之家ip地址归属查询

网站开发 移民,站长之家ip地址归属查询,济南网站制作网站,做外贸没有网站说不改了,可逃不过真香,这次是死也不改版 把他这段话改一改,差不多就是我的心声吧。 『让别人知道怎么维护自己的权利做错什么了吗?我辛辛苦苦维护了好一阵子的项目,开开心心发到网上给大家用,然后你干啥了…

说不改了,可逃不过真香,这次是死也不改版

把他这段话改一改,差不多就是我的心声吧。

『让别人知道怎么维护自己的权利做错什么了吗?我辛辛苦苦维护了好一阵子的项目,开开心心发到网上给大家用,然后你干啥了,躲在我不知道的地方 copy 项目,踩在我身上上架插件,到底谁做错了?目前该揭露的都揭露了,该骂的也骂了,互不相欠!那都是便宜你了』

更新 最后一次

我发现这人有个很奇怪的逻辑,一直在强调他做的比我好,就好像只要做得比我好了,他就什么错都没有了。从一开始在 issue 中回复我,到掘金里的新项目预告,到新项目半成品出炉了之后的话,总是明里暗里说他做得怎么怎么好。

正常的开发者,只要脑袋正常,恐怕都干不出这种 copy 别人代码,然后随便改点地方就作为自己原创发布到 github,甚至是 idea 官网这种事情,更不要提自己用小号给自己评分五星,还问我怎么不想想为什么我下载量比较少。难道觉得这件事情干得很过分,我还反而是没风度了?

我再重申一下我的观点,开源项目你下载下来自己改没什么,但是你作为原创再发布,甚至还拿去上架,这哪个原创作者看到不心塞?想要对开源事业做贡献,正确的做法是 fork 之后再改,改完还可以提 pull request,这才是真正在 github 上做贡献的正确姿势,不然你改一个,他改一个,各自维护各自的,没有一个轮子能做起来的。

从一开始,我就没指望给他的 issue 能起到什么作用,事实上我也没判断错。他面对被我抓了个现成这件事情,毫无愧疚感,也压根不解释为什么删我注释,在我不知情的情况下自行发布上架。他唯一提供的补偿方式就是添加一个迟来的感谢链接,然后很委屈的表示『有时间重构就是了』。

对于这么一个人,我还能说什么呢?多说几句我发现我脾气也上来了,也快管不住自己嘴了。他好歹说了一句人话,那就是这事再闹下去大家都浪费时间。可我想说的是,如果抄袭的人都像他这么明目张胆死不认错,被抄袭的人都忍气吞声,这才是 TMD 有病吧?

好了,发泄够了也就不会再更新了。

最后,希望大家发布原创的时候记得加 LICENSE,这是对自己仅有的一点保障;也希望大家在用别人的代码的时候,带有一丝尊重。

更新 2019-05-13 23:10

那位老哥上传了自己独立完成的代码,我去看了下代码,做了一些花里胡哨的封装。而且在我做了测试之后感觉他的项目完全还不是能用的程度,bug 实在太多。当然,这么短的时间想做出完成度高的东西,确实太难了,只是我真的好惊奇,他发东西出来怼我之前自己都不测试检查一下的吗?boolean 映射成了 num 类型,null 解析不了,空数组直接无响应,排版有各种问题,数据复杂了之后甚至基本的输出文本都是错的,诸如此类的问题不要太多。我也是人太好了,免费帮他当了一把测试人员。以这位老哥吊炸天的编码能力都写出了这么多的 bug,我想我甚至都低估了我当初做这个项目时付出的精力。只是这种努力,恐怕在他看来还是不值一提。

当然,道歉是不可能道歉的,目前来看一切似乎都是我的错。

更新 2019-05-13 11:30

感谢 @吕中宜,@FeelsChaotic 两位提醒我用文本对比工具。

下面附上我提交的两个核心文件的对比结果,额外说明一下,我的代码使用的是1月份的,另外一个人的代码使用的是3月份 github 第一次提交的。

ClassGenerator

对比结果:

106 个相同行

11 个不重要的左边独有行

12 个不重要的右边独有行

4 个不重要的差异行

10 个重要的左边独有行

37 个重要的右边独有行

19 个重要差异行

25 个差异部分

Param

对比结果:

108 个相同行

2 个重要右边独有行

2 个重要差异行

4 个差异部分

更新 2019-05-11 18:20

那位老哥在 github issue 上回复我了

对此我想说的是:

1.有问题可以提 issue, 也可以 fork,心情好的话改了之后还可以提 PR,心情不好就自己用自己的修改版。我个人不能认同因为我的代码不能被直接使用在你个人的项目中,就直接 copy 我的代码,删掉我的注释,改几个命名,然后作为你的原创项目发布到网上去。

2."于是我本地做了大量改动",说实话,或许这位哥们还觉得自己很委屈,觉得自己改了很多代码,但是我觉得比起我从零做起,这点真的不值一提。无论是判断一下空值,还是类型有问题,放我手上都是分分钟解决的问题,犯得着你如此辛苦做这么大奉献吗?

3."此时的代码基本只有json字符串与json对象转换工具类是使用你的库里的",如果你觉得你只用了我这点代码,或者你觉得我这点代码不值一提,为什么不自己重写,反而让我一看到处都是我的代码?

4."硬要说网上的代码都是不允许别人使用的那我也没办法啊",看到这里我真是哭笑不得,这还都是我的错咯?到底是谁该委屈啊?我之前连 LICENSE 都没加一个,难道我会不让别人用?删我注释、自己发布这个核心问题就被这么给忽略掉了?

5."以后有时间我把里面的那个工具类重构下就是了",闹了半天,copy 了整个项目,随便改了几个地方,现在还觉得就用了下工具类?

以下原文

小弟不才,去年学习 flutter 的过程中,搞过几个小玩具,其中就有一个将 json 数据转换成 dart class 的 idea 插件。

gayhub 传送门

不想点的朋友可以看一下 gif

半年多来,随着 flutter 的火热,github 上也有了那么几十个 star。后来我也发布到了全家桶插件官网。陆陆续续也有几千个的下载量了。对于我这个小透明来说,还是挺开心的,不管写得有多烂,总归是有人在用,总归是为 flutter 的生态贡献了自己的一点绵薄之力。

然而就在今天,当我想去看看那些下载量更高的同类项目的时候,很不凑巧的就让我发现了这么一个作品:

先上一张他的 gif 吧

敏感的我,一下子就感觉到了有点不对劲,于是我点开了他的源码开始查看,有如下收获:

我先看了下源码目录

我的

他的

1.ClassGenerator 类名一样的

2.NameValuePair/NamePair 极其相似,而且讲道理,NamePair 这个命名很不自然

3.Param 类名一样

4.Util/Utils 基本没差别

于是我开始对比代码细节

没耐心的朋友可以不用看代码,我以我的人格担保,最后的结论是没错的

ClassGenerator

我的

class ClassGenerator(private val generateComments: Boolean, private val ignoreEmptyOrNull: Boolean) {val classes = mutableMapOf<String, List<Param>>()fun generate(name: String, string: String): String {return try {val parseResult = JsonParser().parse(string)val json: JsonObject? = if (parseResult.isJsonObject) {parseResult.asJsonObject} else if (parseResult.isJsonArray) {parseResult.asJsonArray[0].asJsonObject} else nullval fields = Param.json2Params(json)"class $name {\n${printClassWithParams(fields, 2, name)}\n}\n${buildClasses()}"} catch (jsonParseException: JsonParseException) {jsonParseException.printStackTrace()"error: not supported json"} catch (illegalStateException: IllegalStateException) {illegalStateException.printStackTrace()if (illegalStateException.message?.startsWith("Not a JSON Object") == true) {"error: not supported json"} else {"error: unknown"}}}private fun printClassWithParams(params: List<Param>, space: Int, className: String): String {val commentSb = StringBuilder()val sb = StringBuilder()val tempClasses = HashMap<String, List<Param>>() // 统计子类var spaceStr = ""repeat(space) { spaceStr += " " }val commentPrefix = "$spaceStr *"fun List<Param>.insertComment(): List<Param>  {return if (generateComments) this.map {commentSb.append(commentPrefix).append(" ${it.comment}\n")it} else this}/* 基本类型参数声明与统计 **/val orderedList = params.filter { it.key == "String" || it.key == "int" || it.key == "double" || it.key == "bool" || (!ignoreEmptyOrNull && it.key == "dynamic") }.sortedBy { it.key }.insertComment().map {sb.append("$spaceStr${it.key} ${it.value};\n")it.value}/* 对象类型参数声明与统计 **/val objectList = params.filter { it.key == "object" }.sortedBy { it.value }.insertComment().map {val clazzName = Util.toUpperCaseFirstOne(it.value + "Bean")classes[clazzName] =  it.clazztempClasses[clazzName] = it.clazzsb.append(spaceStr).append(clazzName).append(" ").append(it.value).append(";").append("\n")NameValuePair(clazzName, it.value)}/* 基本类型 list 参数声明与统计 **/val listBaseList = params.filter { it.key.startsWith("List<") }.filterNot { it.key.contains("null") }.sortedBy { it.value }.insertComment().map {sb.append(spaceStr).append(it.key).append(" ").append(it.value).append(";").append("\n")NameValuePair(it.key, it.value)}/* 对象类型 list 参数声明与统计 **/val listList = params.filter { "list" == it.key }.filter { it.clazz != null }.sortedBy { it.value }.insertComment().map {val clazzName = Util.toUpperCaseFirstOne(it.value + "ListBean")classes[clazzName] = it.clazztempClasses[clazzName] = it.clazzsb.append(spaceStr).append("List<").append(clazzName).append(">").append(" ").append(it.value).append(";").append("\n")NameValuePair(clazzName, it.value)}/* dynamic list **/var dynamiclist: List<NameValuePair>? = nullif (!ignoreEmptyOrNull) {dynamiclist = params.filter { it.key == "dynamicList" }.sortedBy { it.value }.insertComment().map {sb.append(spaceStr).append("List<dynamic>").append(" ").append(it.value).append(";").append("\n")NameValuePair(it.key, it.value)}}val tempSpaceStr = "$spaceStr  "/* map.value 转换为对象的静态函数 start **/val fieldName = Util.toLowerCaseFirstOne(className)sb.append("\n").append(spaceStr).append("static ").append(className).append(" fromMap").append("(Map<String, dynamic> map) {").append("\n").append(tempSpaceStr).append(className).append(" ").append(fieldName).append(" = new ").append(className).append("();")orderedList.forEach {sb.append("\n").append(tempSpaceStr).append(fieldName).append(".").append(it).append(" = ").append("map['").append(it).append("'];")}dynamiclist?.forEach {sb.append("\n").append(tempSpaceStr).append(fieldName).append(".").append(it.value).append(" = ").append("map['").append(it.value).append("'];");}objectList.forEach {sb.append("\n").append(tempSpaceStr).append(fieldName).append(".").append(it.value).append(" = ").append(it.name).append(".fromMap(map['").append(it.value).append("']);")}listList.forEach {sb.append("\n").append(tempSpaceStr).append(fieldName).append(".").append(it.value).append(" = ").append(it.name).append(".fromMapList(map['").append(it.value).append("']);")}/* map.value 转换为基础类型 list start **/if (listBaseList.isNotEmpty())sb.append("\n")for ((count, pair) in listBaseList.withIndex()) {sb.append("\n").append(tempSpaceStr).append("List<dynamic> dynamicList").append(count).append(" = map['").append(pair.value).append("'] ?? [];")sb.append("\n").append(tempSpaceStr).append(fieldName).append(".").append(pair.value).append(" = new List();")var function = "o.toString()"when (pair.name) {"List<int>" -> function = "int.parse(o.toString())""List<double>" -> function = "double.parse(o.toString())""List<bool>" -> function = "o.toString() == 'true'"}sb.append("\n").append(tempSpaceStr).append(fieldName).append(".").append(pair.value).append(".addAll(dynamicList").append(count).append(".map((o) => ").append(function).append("));")sb.append("\n")}/* map.value 转换为基础类型 list end **/sb.append("\n").append(tempSpaceStr).append("return ").append(fieldName).append(";\n")sb.append(spaceStr).append("}\n")/* map.value 转换为对象的静态函数 end **//* map.value 转换为 list 的静态函数 start **/sb.append("\n").append(spaceStr).append("static ").append("List<").append(className).append(">").append(" fromMapList").append("(dynamic mapList) {").append("\n").append(tempSpaceStr).append("if (mapList == null) return [];").append("\n").append(tempSpaceStr).append("List<").append(className).append("> list = new List(mapList.length);").append("\n").append(tempSpaceStr).append("for (int i = 0; i < mapList.length; i++) {").append("\n").append(tempSpaceStr).append("  ").append("list[i] = fromMap(mapList[i]);").append("\n").append(tempSpaceStr).append("}").append("\n").append(tempSpaceStr).append("return list;").append("\n").append(spaceStr).append("}").append("\n")/* map.value 转换为 list 的静态函数 end **/// 遍历类中类(主要目的是添加进 classes 统计,而不 append)// 还是由于 dart 不支持内部类导致的tempClasses.forEach { key, value ->printClassWithParams(value, space + 2, key)}val commentString = if (commentSb.toString().isBlank() || commentSb.isEmpty()) {""} else {"\n$spaceStr/**\n$commentSb$spaceStr */\n\n"}return "$commentString$sb"}private fun buildClasses(): String {val sb = StringBuilder()// 开始定义类classes.forEach { key, value ->sb.append("\n").append("class").append(" ").append(key).append(" ").append("{").append("\n").append(printClassWithParams(value, 2, key)).append("}").append("\n")}return sb.toString()}
}
复制代码

他的

class ClassGenerator {val classes = mutableMapOf<String, List<Param>>()fun generate(name: String, jsonText: String): String {return try {val fields = Param.json2Params(JsonParser().parse(jsonText).asJsonObject)"class $name {\n${printClassWithParams(fields, 2, name)}\n}\n${buildClasses()}"} catch (jsonParseException: JsonParseException) {jsonParseException.printStackTrace()"error: not supported json"} catch (illegalStateException: IllegalStateException) {illegalStateException.printStackTrace()if (illegalStateException.message?.startsWith("Not a JSON Object") == true) {"error: not supported json"} else {"error: unknown"}}}fun generate(name: String, fields: JsonObject): String {return try {"class $name {\n${printClassWithParams(Param.json2Params(fields), 2, name)}\n}\n${buildClasses()}"} catch (jsonParseException: JsonParseException) {jsonParseException.printStackTrace()"error: not supported json"} catch (illegalStateException: IllegalStateException) {illegalStateException.printStackTrace()if (illegalStateException.message?.startsWith("Not a JSON Object") == true) {"error: not supported json"} else {"error: unknown"}}}private fun printClassWithParams(params: List<Param>, space: Int, className: String): String {val sb = StringBuilder()val tempClasses = HashMap<String, List<Param>>()var spaceStr = ""repeat(space) { spaceStr += " " }val orderedList = params.filter { it.key == "String" || it.key == "int" || it.key == "double" || it.key == "bool" || it.key == "num" }.sortedBy { it.key }.map {sb.append("$spaceStr${it.key} ${it.camelWord};\n")NameValuePair(it.value, it.camelWord)}val objectList = params.filter { it.key == "object" }.sortedBy { it.value }.map {val clazzName = Utils.toUpperCaseFirstOne(it.value + "Bean")classes[clazzName] = it.clazztempClasses[clazzName] = it.clazzsb.append(spaceStr).append(clazzName).append(" ").append(it.camelWord).append(";").append("\n")NamePair(it.camelWord, clazzName, it.value)}val listBaseList = params.filter { it.key.startsWith("List<") }.sortedBy { it.value }.map {sb.append(spaceStr).append(it.key).append(" ").append(it.camelWord).append(";").append("\n")NamePair(it.camelWord, it.key, it.value)}val listList = params.filter { "list" == it.key }.sortedBy { it.value }.map {val clazzName = Utils.toUpperCaseFirstOne(it.value + "ListBean")classes[clazzName] = it.clazztempClasses[clazzName] = it.clazzsb.append(spaceStr).append("List<").append(clazzName).append(">").append(" ").append(it.camelWord).append(";").append("\n")NamePair(it.camelWord, clazzName, it.value)}val tempSpaceStr = "$spaceStr  "/*** 构造*/sb.append("\n").append(spaceStr).append(className).append("({")orderedList.forEach {sb.append("this").append(".").append(it.value)sb.append(", ")}objectList.forEach {sb.append("this").append(".").append(it.camelKey)sb.append(", ")}listList.forEach {sb.append("this").append(".").append(it.camelKey)sb.append(", ")}listBaseList.forEach {sb.append("this").append(".").append(it.camelKey)sb.append(", ")}if (sb.endsWith(", ")) {sb.delete(sb.lastIndexOf(", "), sb.length)}sb.append("});\n")sb.append("\n").append(spaceStr).append(className).append(".fromJson").append("(Map<String, dynamic> json) {").append(tempSpaceStr)orderedList.forEach {sb.append("\n").append(tempSpaceStr).append("this").append(".").append(it.value).append(" = ").append("json['").append(it.name).append("'];")}objectList.forEach {sb.append("\n").append(tempSpaceStr).append("this").append(".").append(it.camelKey).append(" = ").append("json['").append(it.value).append("'] != null? ").append(it.key).append(".fromJson(json['").append(it.value).append("']) : null;")}listList.forEach {sb.append("\n").append(tempSpaceStr).append("this").append(".").append(it.camelKey).append(" = ").append("(json['").append(it.value).append("'] as List)!=null?(json['").append(it.value).append("'] as List).map((i) => ").append(it.key).append(".fromJson(i)).toList():null;")}listBaseList.forEach {sb.append("\n")sb.append("\n").append(tempSpaceStr).append("List<dynamic> ").append(it.camelKey).append("List").append(" = json['").append(it.value).append("'];")sb.append("\n").append(tempSpaceStr).append("this").append(".").append(it.camelKey).append(" = new List();")var function = "o.toString()"when (it.key) {"List<int>" -> function = "int.parse(o.toString())""List<double>" -> function = "double.parse(o.toString())""List<bool>" -> function = "o.toString() == 'true'"}sb.append("\n").append(tempSpaceStr).append("this").append(".").append(it.camelKey).append(".addAll(").append(it.camelKey).append("List").append(".map((o) => ").append(function).append("));")}sb.append("\n").append(spaceStr).append("}\n\n")sb.append(spaceStr).append("Map<String, dynamic> toJson() {\n").append(tempSpaceStr).append("final Map<String, dynamic> data = new Map<String, dynamic>();")orderedList.forEach {sb.append("\n").append(tempSpaceStr).append("data['").append(it.name).append("'] = ").append("this").append(".").append(it.value).append(";")}objectList.forEach {sb.append("\n").append(tempSpaceStr).append("data['").append(it.value).append("'] = ").append("this").append(".").append(it.camelKey).append(".toJson();")}listList.forEach {sb.append("\n").append(tempSpaceStr).append("data['").append(it.value).append("'] = ").append("this").append(".").append(it.camelKey).append(" != null?this.").append(it.camelKey).append(".map((i) => i.toJson()).toList():null;")}listBaseList.forEach {sb.append("\n").append(tempSpaceStr).append("data['").append(it.value).append("'] = ").append("this").append(".").append(it.camelKey).append(";")}sb.append("\n").append(tempSpaceStr).append("return data;\n")sb.append(spaceStr).append("}\n")tempClasses.forEach { key, value ->printClassWithParams(value, space + 2, key)}return sb.toString()}private fun buildClasses(): String {val sb = StringBuilder()classes.forEach { key, value ->sb.append("\n").append("class").append(" ").append(key).append(" ").append("{").append("\n").append(printClassWithParams(value, 2, key)).append("}").append("\n")}return sb.toString()}
}
复制代码

是不是一个模子刻出来的?大量的函数名、属性名都是一致的,换行空行也都是一致的

NameValuePair/NamePair

我的

由于我已经将 NameValuePair 用 kotlin 改写了,下面的代码是从 git 提交记录里找到的

/*** Created by zhangll on 2018/8/3.*/
public class NameValuePair {String name;String value;public NameValuePair(String name, String value) {this.name = name;this.value = value;}
}
复制代码

他的

public class NamePair {private String camelKey;private String key;private String value;public NamePair(String camelKey, String key, String value) {this.camelKey = camelKey;this.key = key;this.value = value;}public String getCamelKey() {return camelKey;}public void setCamelKey(String camelKey) {this.camelKey = camelKey;}public String getKey() {return key;}public void setKey(String key) {this.key = key;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}
}
复制代码

乍一看似乎不一样,其实他只是多写了 getter setter,又加了一个驼峰命名功能的字段。我怎么看出来一致的呢?因为 NameValuePair 严格来说,就应该给属性命名 name 和 value。而另一个人的类名叫 NamePair,中间偏偏少了个 Value ,属性命名却又是 key(不是理论上的 name)、value,这是为什么呢?明眼人应该一看就知道了。

Param

我的

/*** Created by zhangll on 2018/8/3.*/
public class Param {String key;String value;List<Param> clazz;String comment;/**** @param key 变量名* @param object 变量内容* @return*/public static Param makeParam(String key, Object object) {if (object == null || "null".equals(object.toString())) {return new Param("dynamic", key, null, object);}if (object instanceof JsonObject) {JsonObject jsonObject = (JsonObject) object;return new Param("object", key, json2Params(jsonObject), jsonObject);} else if (object instanceof JsonArray) {JsonArray jsonArray = (JsonArray) object;if (jsonArray.size() != 0) {Object obj = jsonArray.get(0);if (obj instanceof JsonObject) {return new Param("list", key, json2Params(jsonArray.get(0).getAsJsonObject()), jsonArray);} else if (obj instanceof JsonArray) {return new Param("dynamicList", key, null, object);} else {Param temp = makeParam("placeholder", obj);if (temp.key.equals("dynamic")) {return new Param("dynamicList", key, null, object);}return new Param("List<" + temp.key + ">", key, null, object);}} else {return new Param("dynamicList", key, null, object);}} else if (tryParseBoolean(object)) {return new Param("bool", key, null, "true".equals(object.toString()));} else if (tryParseInt(object)) {return new Param("int", key, null, Integer.parseInt(object.toString()));} else if (tryParseLong(object)) {return new Param("int", key, null, Long.parseLong(object.toString()));} else if (tryParseDouble(object)) {return new Param("double", key, null, Double.parseDouble(object.toString()));} else if (tryParseFloat(object)) {return new Param("double", key, null, Float.parseFloat(object.toString()));} else {return new Param("String", key, null, object.toString());}}public static List<Param> json2Params(JsonObject jsonObject) {List<Param> list = new ArrayList<>();for (Object o : jsonObject.entrySet()) {Map.Entry entry = (Map.Entry) o;list.add(Param.makeParam(entry.getKey().toString(), entry.getValue()));}return list;}private static boolean tryParseInt(Object object) {try {int i = Integer.parseInt(object.toString());return true;} catch (Exception e) {return false;}}private static boolean tryParseLong(Object object) {try {long i = Long.parseLong(object.toString());return true;} catch (Exception e) {return false;}}private static boolean tryParseDouble(Object object) {try {double d = Double.parseDouble(object.toString());return true;} catch (Exception e) {return false;}}private static boolean tryParseFloat(Object object) {try {float f = Float.parseFloat(object.toString());return true;} catch (Exception e) {return false;}}private static boolean tryParseBoolean(Object object) {String b = object.toString();return Objects.equals(b, "true") || Objects.equals(b, "false");}public Param(String key, String value, List<Param> clazz, Object content) {this.key = key;this.value = value;this.clazz = clazz;if (content == null) return;// 注释处理this.comment = value + " : " + content.toString().replaceAll("\n", "");}@Overridepublic String toString() {return "Param{" +"key='" + key + '\'' +", value='" + value + '\'' +", classes=" + clazz +'}';}
}
复制代码

他的

public class Param {String key;String value;String camelWord;List<Param> clazz;/**** @param key 变量名* @param object 变量内容* @return*/public static Param makeParam(String key, Object object) {if (object instanceof JsonObject) {JsonObject jsonObject = (JsonObject) object;return new Param("object", key, json2Params(jsonObject));} else if (object instanceof JsonArray) {JsonArray jsonArray = (JsonArray) object;if (jsonArray.size() != 0) {Object obj = jsonArray.get(0);if (obj instanceof JsonObject) {return new Param("list", key, json2Params(jsonArray.get(0).getAsJsonObject()));} else {Param temp = makeParam("placeholder", obj);return new Param("List<" + temp.key + ">", key, null);}} else {return new Param("list", key, null);}} else if (tryParseBoolean(object)) {return new Param("bool", key, null);} else if (tryParseInt(object)) {return new Param("int", key, null);} else if (tryParseLong(object)) {return new Param("num", key, null);} else if (tryParseDouble(object)) {return new Param("double", key, null);} else if (tryParseFloat(object)) {return new Param("double", key, null);} else {return new Param("String", key, null);}}public static List<Param> json2Params(JsonObject jsonObject) {List<Param> list = new ArrayList<>();for (Object o : jsonObject.entrySet()) {Map.Entry entry = (Map.Entry) o;list.add(Param.makeParam(entry.getKey().toString(), entry.getValue()));}return list;}private static boolean tryParseInt(Object object) {try {int i = Integer.parseInt(object.toString());return true;} catch (Exception e) {return false;}}private static boolean tryParseLong(Object object) {try {long i = Long.parseLong(object.toString());return true;} catch (Exception e) {return false;}}private static boolean tryParseDouble(Object object) {try {double d = Double.parseDouble(object.toString());return true;} catch (Exception e) {return false;}}private static boolean tryParseFloat(Object object) {try {float f = Float.parseFloat(object.toString());return true;} catch (Exception e) {return false;}}private static boolean tryParseBoolean(Object object) {String b = object.toString();return Objects.equals(b, "true") || Objects.equals(b, "false");}public Param(String key, String value, List<Param> clazz) {this.key = key;this.value = value;this.camelWord = Utils.toUpperCaseParams(value);this.clazz = clazz;}@Overridepublic String toString() {return "Param{" +"key='" + key + '\'' +", value='" + value + '\'' +", classes=" + clazz +'}';}
}
复制代码

又是一个模子刻出来的。除了我新增了注释功能和部分 bug 修复导致的代码变动,他新增了驼峰命名功能。

Util/Utils

我的

/*** Created by zhangll on 2018/8/3.*/
public class Util {/*** 将字符串复制到剪切板。*/public static void setSysClipboardText(String writeMe) {Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();Transferable tText = new StringSelection(writeMe);clip.setContents(tText, null);}// 首字母转大写public static String toUpperCaseFirstOne(String s){if(Character.isUpperCase(s.charAt(0)))return s;elsereturn (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();}// 首字母转小写public static String toLowerCaseFirstOne(String s){if(Character.isLowerCase(s.charAt(0)))return s;elsereturn (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();}// 将 string 写入文件public static void writeToFile(Project project, VirtualFile file, String content) {Runnable runnable = () -> {try {file.setBinaryContent(content.getBytes());} catch (IOException e) {e.printStackTrace();}};WriteCommandAction.runWriteCommandAction(project, runnable);}
}
复制代码

他的

public class Utils {/*** 将字符串复制到剪切板。*/public static void setSysClipboardText(String writeMe) {Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();Transferable tText = new StringSelection(writeMe);clip.setContents(tText, null);}// 首字母转大写public static String toUpperCaseFirstOne(String s) {if (s.contains("_")) {String[] a = s.split("_");StringBuilder builder = new StringBuilder();for (String anA : a) {if (Character.isUpperCase(anA.charAt(0)))builder.append(anA);elsebuilder.append(Character.toUpperCase(anA.charAt(0))).append(anA.substring(1));}return builder.toString();}if (Character.isUpperCase(s.charAt(0)))return s;elsereturn (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();}// 下划线参数转驼峰public static String toUpperCaseParams(String s) {if (s.contains("_")) {String[] a = s.split("_");StringBuilder builder = new StringBuilder();for (int i = 0; i < a.length; i++) {if (i==0){builder.append(a[i]);}if (Character.isUpperCase(a[i].charAt(0)))builder.append(a[i]);else if (i != 0)builder.append(Character.toUpperCase(a[i].charAt(0))).append(a[i].substring(1));}return builder.toString();}return s;}// 首字母转小写public static String toLowerCaseFirstOne(String s) {if (Character.isLowerCase(s.charAt(0)))return s;elsereturn (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();}// 将 string 写入文件public static void writeToFile(VirtualFile file, String content) {try {file.setBinaryContent(content.getBytes());} catch (IOException e) {e.printStackTrace();}}
}
复制代码

写文件的代码好像有不同?没关系,我 git 里拉老代码出来

// 将 string 写入文件
public static void writeToFile(VirtualFile file, String content) {try {file.setBinaryContent(content.getBytes());} catch (IOException e) {e.printStackTrace();}
}
复制代码

所以,唯一的不同就是我类头有注释,而他多了一个驼峰命名的方法。

放上另一个人的项目地址,有闲心的朋友可以自己去看

github.com/xlyasdasd/F…

总结一下

如果就 copy 一下我的代码过去用,其实我肯定也没什么,按道理来说作为一个程序猿我还应该觉得开心才是。

但是 copy 了我整个项目,又极其不专业的只改了几个不痛不痒的地方,改得此地无银三百两,留着项目结构、类命名、方法命名、空行、换行这些个人风格浓重的东西不动,我是 Kotlin 写的地方他就是 Kotlin,我用 Java 写的地方他就是 Java, 难道是因为核心逻辑看不懂不敢改动吗?既然能自己加上驼峰命名的功能,想来也不至于。

如果只是 copy 项目也就罢了,他甚至还发布到了全家桶插件的官网,如果不是因为下载量比我自己的插件还高,恐怕这事我到死都不会知道。

当然,他没什么错,是我自己没给开源项目加上 LICENSE。但想来就算我有 LICENSE,按他能去发布插件这个勇气来看,只怕也是不在乎的。

有朋友跟我说,我应该开心,应该有成就感,因为至少这证明我做的东西是有价值的,但我觉得事情不应该这么去看待。我花了心思去写出来的东西,我心肝情愿的开源,我心肝情愿的给别人用,但是拿了我的心血去换个包装贴上他自己的牌子,这谁能接受?

作为一个喜欢 flutter 的开发者,我也不至于因为这事就丧了气,尽管也付出了不少时间,做了不少迭代,但毕竟只是一个小玩具项目而已。只是这次被好好的上了一课,以后不论多小的项目,LICENSE 是一定不能少的。

最后,Flutter 真香!

转载于:https://juejin.im/post/5cd5ad9fe51d453a393af4e1

http://www.lbrq.cn/news/2361745.html

相关文章:

  • 网站 建设 现状超级外链工具
  • 山东网站建设推广武汉seo 网络推广
  • 福州市晋安区建设局网站怎么在百度免费推广
  • 档案信息网站建设网站软件开发
  • 济南网站开发建设广告接单平台有哪些
  • 北京建站工具怎么推广自己的网站?
  • 免费开源企业cmsseo推广岗位职责
  • 抚顺网站制作长沙企业关键词优化
  • vs网站制作百度搜索优化建议
  • 深圳光明网站建设免费网站推广软件
  • 网站系统使用手册营销型网站的类型有哪些
  • 从用户需求看b2b网站的营销策略长沙营销网站建设
  • 两学一做知识问答网站今日国内热点新闻头条事件
  • 创建网站要多少钱关键词搜索引擎排名查询
  • 网站添加友情链接网上在哪里打广告最有效
  • 江苏缘生源建设工程有限公司网站搜外网友情链接
  • 漂亮大气的装潢室内设计网站模板 单页式html5网页模板包如何快速搭建一个网站
  • 艺术品商城网站开发软件测试培训班多少钱
  • 如何优化网站排名网络优化工程师有多累
  • 网页制作的公司找时代创信凌哥seo技术博客
  • 德阳北京网站建设做网站关键词优化的公司
  • 网站建设公司创业软件编程培训学校排名
  • seo网站优化推广网站的友情链接是什么意思
  • 网站商城的意义培训网站模板
  • 动画制作软件下载安装seo数据
  • 可以做问答的网站关键词规划师工具
  • p2p网站如何做测试合肥网站优化平台
  • 品牌网站推广海南百度总代理
  • 寻找网站建设_网站外包昆山网站制作哪家好
  • 有什么网站可以做试题广州网站优化
  • 从零开发足球比分APP:REST API与WebSocket的完美搭配
  • 生产问题排查-数据库连接池耗尽
  • 在百亿流量面前,让“不存在”无处遁形——Redis 缓存穿透的极限攻防实录
  • Java线程池深度解析与Spring Boot实战指南
  • 【字节跳动】数据挖掘面试题0019:带货直播间推荐:现在有一个带货的直播间,怎么把它精准地推送给有需要的用户
  • 春秋云镜 initial