duangsuse::Echo
710 subscribers
4.23K photos
127 videos
583 files
6.44K links
import this:
美而不丑、明而不暗、短而不凡、长而不乱,扁平不宽,读而后码,行之天下,勿托地上天国。
异常勿吞,难过勿过,叹一真理。效率是很重要,盲目最是低效。
简明是可靠的先验,不是可靠的祭品。
知其变,守其恒,为天下式;穷其变,知不穷,得地上势。知变守恒却穷变知新,我认真理,我不认真。

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
不过,在我经历无数烂代码的洗礼后,终于找到了bug的源头(一个str属性配置没适配...) 现在终于可以移植过来了emmmm...
duangsuse::Echo
不过,在我经历无数烂代码的洗礼后,终于找到了bug的源头(一个str属性配置没适配...) 现在终于可以移植过来了emmmm...
有意思的是这位大神作者(可惜代码质量怎么那么差) 写出的代码虽然很好用,但其实它是薛定谔程序! 测试里应用范围内无变量,但程序行为却间隔1次时好时坏!
This media is not supported in your browser
VIEW IN TELEGRAM
这个故事告诉我们,不要尝试复制粘贴自己的代码然后做出改动。多抽提出函数调用。不然出了问题会非常麻烦。(这位大佬是把 横向纵向 的所有区别代码都用 self.op = 的形式支持,这又走另一个极端了... )
This media is not supported in your browser
VIEW IN TELEGRAM
不过说起来这次重构限制也蛮大的。目的只是要支持的几个控件里的一小个,因为原代码质量和工具不好 费了一天时间才移植一个 Widget, 而且还阻塞了我其他任务
也是因为重构时要求在完整正确的代码上改。不然一边改一边加特性还要修问题,在自己不熟悉UI框架的情况下很难正确。

要是这个作者能把他 a = initial; a = op(a, b) | a = initial; if p(a): a = b 的这种坏习惯改一改,学会多建立私有方法/局部函数 就好了,我看充满重赋值的代码时是相当头疼的……
不能怪我抱怨 ,因为这代码真的是让人无法忍受…… 你看这个,只有 anchor 一个变量,他竟然在一个循环里,给这个玩意写了两遍, 而且if体只引用到了self.... 面向对象的优势何在
唉真是头疼呢。要是这些大佬能在写的时候注意点,就不会出现这么多难以复用的代码了
不过这也不能,如果只是修改代码风格、压行的话,是起不到简化作用的,不同的调用参数太多了。 我吐嘈的是这个人没做到一些最基础的复用,看起来就像是 python wtf.py 的面向查错编程一样(当然对 Tk 的 GUI 有些问题也迷所以必须测试,但不意味着你可以把冗余逻辑复制粘贴而不是化作复用函数)

如果要进一步提升代码质量,不使用高阶函数是很难实现的(那意味着你没法把模板化函数命名作动词,然后用另一些动词调用它从而实现更高层次的复用)
用高阶函数(当然那是概念上的名字,工程中我把函数值命名为和函数/方法一样的动词)才能实现更好的效果,如图把表述式代码和定义式代码比较,它简直像汇编一样眼花……

其实相关知识许多人也知道,但是他们的代码复用意识淡薄,而且现在框架丛生,人们越来越懒得写自己的抽象了;开始习惯把自己禁锢在别人提供的安乐窝里,照着惯用法一点一点堆积木。
即便不是低级错误也应该是可以预防的错误啊…… 怎么看都是原有 888 端口加个 /pma 都直接越权访问。 无非是外部代码插入server不当或是验证时序/接口失当级别的问题,在程序封包层错误都可以导致此问题,还不是很渣..
Oh come on ... 这可爱的 truthy value... 我还以为是 0.0>0.5 或者自动数值类型提升出问题了呢。 我开始怀念 Ruby 里只有 nil 和 false 的 if / || 表达式了。
This media is not supported in your browser
VIEW IN TELEGRAM
Python 里感觉用个 (a if p else b) 都不敢乱写,乱写会出岔子/影响预期性能(开个玩笑)/etc.
HowFarIllGo
1.9 KB
对了,我这里有份迪斯尼动画电影 Moana 主题曲的(半完成)音高线,用过我 Hachiko(当然我知道没人用 哪怕是 producer. 嘿嘿)的人可以拿去现场演奏(
啊... 花了好大力气它终于 works 了,本来还想一笔带过的,花了一天…… 不得不佩服写 GUI 控件的人的勇气,我被迫从它的烂代码里了解了它的具体操作,不过重构真是无聊,相信我,别做 refactor man, 一点也不好玩。
This media is not supported in your browser
VIEW IN TELEGRAM
不过老实说我挺喜欢定义式代码的 #Python
比如
x = self._valPixels(float(value))
后,
w=self._wid.winfo_width()
if x + half_width > w: x = w - half_width
elif half_width > x: x = half_width
咱给简化成一句话了,所以可以直接写参数里
x=max(TtkScale._bounds(x, self._wid.winfo_width(), half_width), half_width)
其中,
def _bounds(n, max, sub): return max-sub if n+sub > max else n

看来我果然还是讨厌写 if while ( 如果抽象程度更高 何必重赋值呢
以此类推,五六处这样的代码我都用我的方法简化了。 既然弄完了不如就顺便讲点啥……
面向对象基础设计模式小讲堂 🙉 #OOP #learn
我们要介绍 override(覆写), overload(重载, 重新的重) 两个基础多态、以及 Mix-in(混入), Delegate(代理) 这两个设计模式
注:咱不懂 JS 的 prototype chain 也不太懂 Python ,说得概念化一点。
当然我一贯的习性是先讲原理,看官如果讨厌的话就先看后面简单的。 😙

面向对象的基础,除了易语言和其他伪面向对象所谓的 this 参数特殊化处理(最基础的"主语this"封装),关键有三点:
抽象,意味着应该有只指定调用型参(formal parameter)的 interface ,从而允许其他类型覆写。实例如所有东西(门/盒子/...)都可破坏,但破坏的实现是按它的具体属类决定的。
继承,意味着有 Duck: Animal 这种子类型关系,即前者具有后者的所有成员。有了继承和 public(公开)/protected(族内)/private(私下) 的可访问性区分,可以实现对模块外隐藏的代码 抽象-提出为方法 复用,
如把 for (i=0;i<n;i++) op(); 建模为一个 class , i 即成它的私有属性、 op() 即成它的私有方法。如果 op 是构造器参数等可变动项,不就是一种 Iterable 了么🤪
有些语言如 C++ 有多继承,可混入两个超类,但那样对常见模型来说过于复杂
有些语言如 Ruby,Python 有主要支持 mixin 的多继承,(Ruby 的 module Mix; class A < T; extend Mix; Py 的 class A(T, Mix): ) 可以把插入方法解析链上(A.ancestors / A.mro()) 但对构造器调用
多态,本身是「同一名字引用不同含义」的意思,但一般意味着通过子类型的兼容性,你可以在子类里覆盖其超类的方法行为,比如 java.util.function.Function 就严重依赖这个东西(Java 8 的 lambda 当然也基于此)

多态意味着可以创建函数值,它是 Listener 等惯用法所必须的特性(T=Runnable; T oper = new T() { void run(){print(1);} } 这种 "anonymous subclass" 就利用了多态,不然你以为 oper.run() 的 receiver(this=oper) 是怎么知道调用其 T.run 实际做 print(1)
也有人说,对象的本质不是分配出个 struct 存储空间的指针或者 GC object,而是一个强类型的函数式闭包(可依赖外部变量的函数值,这个函数就是 send 方法解析+执行函数、依赖的变量就是 this)

多态的本质是 type checker 的子类型(subtype)兼容+运行时方法解析,方法解析是重点、继承树优化处理点,因为子类型意味着如参数/局部变量可以兼容其要求「表象类型」的所有「实际类型」,如 Animal + Duck

在 Java 里一般用 @Override 标注覆写方法,但这不是必须的。 override(子类型多态) / Generic(parameterized type, 参数化多态) 和 overload 同属多态,但 overload 属于可以静态完成的特殊多态(ad-hoc polymorhism),想想编译器可以通过 type signature 查找的方法简单找到要调用的方法,不需要在运行期基于对象实际类型完成方法派发。

对于 JVM/Ruby/Python 的对象都存有其 type: a.getClass() / a.class / type(a) 所以可以有其VM内建的派发方式,不过在相对底层(无 GC 而用指针)的语言里一般有两种多态方法解析方式: virtual table (虚方法表) / fat pointer (双指针) ;前者意味每个对象都存储其实际类型虚表指针、后者则是每个引用都存储对象的实际类型(优点是局部分配不需要vtable,省内存了)
顺便提一句: Python 目前是 gradual type & consistence type 的语言,分别意味可选标注类型/Any 类型与任意类型自动强制转换
VM:语言用虚拟机(线性指令解释器)/GC:垃圾回收器,分配对象

类(class)有三种基础成员:构造器(constructor)、属性(property, 或者说名词/类层次的 val/var)、方法(method, 或者说动词/类层次的 local fun) ,当然 inner class 和命名空间意义上的 inner class 就是语言特定的了。(基本都是语法糖/特殊命名解析

Java 的属性是用方法实现的,它的 "field" 概念不叫属性,其暴露了过于底层的东西,使得程序员被迫选择是否定义冗余的 private this.x;T getX() ,或者完全放弃可扩展性;这是不重视设计模式优雅性的表现。
一般的 OOP 语言都会支持把 property initializer 和它的类型定义放一起,然后可以集合并生成默认构造器,但记住这只是简写法,构造器应当存在。

方法的继承是基于方法解析,属性继承则是通过构造器调用。无论程序员是否显式写出,超类链(直到Object)上的所有构造器都会被调用,一般而言是超类优先调用,那样子类构造器就能访问超类属性。
所以不允许构造器访问 non-final (open for override) 的属性,因为如果它在子类里被覆盖 超类就会访问到 uninitialized property 。 这种情况属性换成 protected 方法即可。
**更新:如果 initializer 在子类被覆盖就不进行初始赋值,对超类来说也太难判断了。经过测试我才发现那样只是令依赖 override val 的属性得到旧的值:
abstract class A(px:Int) { open val p=px; val p1=p+1 }
class B:A(0) { override val p=2 }
B().p1 //1

open class A { open val p=0; val p1=p+1 }
class B:A() { override val p=1 }
B().p1 //1
当然如果有在构造器里对子类成员的环形引用,是可能访问 uninitialized 的。继承在构造器里必须是单向的。(不必注意 这个不常见)

注意即便对象不是 hash 表(动态对象)实现(Ruby/Python/JavaScript),它和它所有超类的未初始化属性所占用的内存空间也是可以被静态计算出来的,new 将分配和构造器调用同时进行。

https://github.com/duangsuse-valid-projects/Share/blob/master/Others/LuaOOP/oop.lua 这里有一个为 Lua 实现面向对象 new/inherience 的

最基础的封装好多语言都有,我们这次不讲那个可用于支持链式调用传递this上下文的。(因为它的功能局限于此,尽管this成员和global变量的区分隐含一个链结构,那是可编译期静态解决的)
对于不使用 interface 进行"抽象"的返回类型检查,在 Kotlin 里可以用 Nothing (实际上不会返回的操作如 System.exit() / throw Error() 为此类型) 来略过。虽然抽象方法的概念是无需实现体即可声明,它的「实现」与否也是相对其子类而言的。

Mixin 呢,表示隐式(无需指定 receiver)访问不在超类链里方法的设计。假设小明要创建一个 class Duck extends Animal, 但他发现 Animal 里有一群冗余方法可以复用: propertyKeys(), getProperty(), setProperty() 但生成它们返回值的方法需要 super (即 Animal) 对象,而且,因为他在扩展别人已继承 Animal 的类,无法定义出 ProperAnimal 而必须直接继承指定 ? extends Animal
他可以选择复制粘贴,但除了 Duck 他还有一大堆一样的 Animal 子类要定义。不能继承自消除模板化的超类,也不能覆盖超类的抽象方法来提供数据从而复用其逻辑,怎么办?
Java 没有多继承,也没有 Mixin 。 假设它有的话,或许我们可以选择用 Mixin (注意概念上它们全都是 private 方法,不可参与方法解析的)。

interface AnimalBoilerplates extends AnimalKind {
default Set<String> mpropertyKeys() {/**/}
default Object mgetProperty(String key) {/**/}
default void msetProperty(String key, Object value) {}
}
class MoreDuck extends HerDuck implements AnimalBoilerplates {
Set<String> propertyKeys() { return mpropertyKeys(); }
}

当然这个做法也是比较鸡肋的,毕竟是在扩展别人的类库,只是个例子哈哈。