yesterdaysun 最近回复了
感觉像是精确覆盖问题(Exact Cover), 可以搜一下相关的算法试试
为啥没有评论, 我看完了, 觉得写的还挺好的, 虽然内容比较基础, 但是整体感觉是经过精心编排的, 提到了 SOLID 设计原则, 也精选了常见实用的几个设计模式.
提点建议, 现在设计模式这块太卷了, 各种书啊文章啊, 想要出彩得来点特别的干货, 比如举的代码例子, 面向初学者, 这些普普通通的实现类就够了, 但是要进阶的话, 最好结合各个知名框架, 讲它们是怎么使用设计模式的, 比如 Spring,MyBatis 里的, 或者 Apache Commons 里的设计模式, 或者 JDK 里的设计模式, 不过这样可能每个模式都要 2.5w 字了.
或者也可以在设计原则上加深一下, 初学者一般重点会在 23 个设计模式上, 但其实在我看来各个设计原则才是根本, 以设计原则的视角去深入剖析各个设计模式的原始初衷, 使用场景和设计妥协应该会很有帮助
还可以结合不同的语言, 反正标题也没写必须 Java 嘛, 不同语言对设计模式有不同程度的支持, 静态语言和动态语言的不同也会导致有些设计模式不需要写的那么繁琐了
按 member_id 和 category_id 分组, 然后用 case when, 如果 exist select is_cover=2 的数据, 则返回 id,否则 select is_cover=1 order by create_time desc limit 1 的 id, 以这个结果作为子查询再套一层 join id 把其他字段查出来
我稍微尝试代入一下你领导的视角: 你这个设计太没有前瞻性了, 我见过太多"按需求白描"的设计了, 优惠券这种东西我太清楚了, 以后肯定要大改, 为啥不一次性弄好, 我们系统其它地方都是按照一定余量一定灵活度设计的, 你为啥不照着那些来, 这才不是什么"过度设计", 而是有前瞻性的规划, 现在那些人说试验性需求, 过两天立马加大力度要你改, 看你到时候怎么办
我也尝试代入一下你的视角: 产品都说是小需求了, 加两张表足够了, 反正就两张表, 出问题改起来也容易, 字段不多, 没什么复杂的东西, 需求来了改起来轻轻松松, 余量刚刚好, 反正产品也要迭代的, 我这是"敏捷"的做法
以上纯属 YY, 反正我看来大概是沟通问题, 你们并没有一些共识, 你可能看不惯系统其它地方的"过度设计", 这次尝试一下"刚刚好的设计", 然后被领导发现, 就被批了, 那可以就这个机会讨论一下, 到底其他人怎么看待"过度设计", 如果能说服别人最好, 最差也可以知道其他人到底是怎么想的, 是真的碰到过坑, 小心谨慎的做法, 还是纸上谈兵, 夸夸其谈, 这个时候也不必说服对方了, 做你该做的就好了, 可以迫于领导压力, 按她的做, 也可以吸收你觉得好的设计用上, 也可以尝试坚持自己的做法.
我一般不上来把人想的太坏, 先当他是个"理性人", 看看确实有没有一些道理, 当然不排除最坏的情况, 就是领导看你不爽, 如果最终你的结论是这个, 那就只有第 36 计了
有时会用在缓存的 key 上, 比如这个缓存需要一个一个 id 加另一个 id 才是唯一的, 之前可能会要字符串连接之类的, 换成对象就比较好, 不过只是纯感觉, 没有测过两者性能有多大差, 更多是为了类型安全和简单性可读性, 反正有 lombok 或者 record, equals 和 hashcode 都是自动的
如果总条数不是特别重要, 可以考虑只精确查询特定数量以下的条数, 比如 10000 条, 10000 条之上统一显示 10000 或者提示超过 10000, 之下才精确计算
可以先用 select 1 from t where xxx limit 10000,1 确定是不是超过 1 万条, 超过则 total 直接写 10000
如果没超过再 select count(1) form t where xxx
1 万条可能大了点, 可以换成 1 千条之类的, 应该可以提高一点 count 的速度, 但是效果可能不会很好, 有条件还是上 ES 吧
我觉得相比老的 j2ee, Spring/SpringBoot 已经算轻的了, 虽然离云原生的标准还差了不少, 但是毕竟也是有其他优势的, 就是生态好, 工具 /社区丰富, 也隐藏了一些复杂的底层细节, 所谓"笨重"应该不是首要考虑的问题
此外, Getter/Setter 我觉得是必要的, 如果是真纯数据类型, 已经有 record 类了, 如果要加上一些行为的话, 隐藏在 Getter/Setter 后面是最方便自然的了, 如果只是怕麻烦, 可以用 lombok, 很方便
IService/ServiceImpl 这个应该是如果是接口的话, 底层就会用 JDK 动态代理实现, 如果是有一个 Service 的话, 用的 CGLIB, 据说性能稍微差一点, 反正我的话, 如果接口有多个实现, 就用接口, 如果只是单个实现, 就不要接口
你说一个请求要好几层的话, 这个和接口什么的没有关系, 是设计的问题, 要看你的项目架构怎么设计和定义的了, 一般都得分个请求层 /服务层 /数据层之类的, 如果说 3 层都闲多, 要目你的项目太简单是真不需要, 要么就是还没遇到合在一起遇到的麻烦事.
如果说的是单 Service 层有好几层, 那要看具体情况了, 如果只是单单说是公司规定, 全是模版代码, 我建议如果不能说服老大, 那自己做一个模版代码生成器会方便很多
空数组下这个 if (list)也不对吧, 我选择 if (list?.length)
顺便我也说一个应该算得上你说的这种认知问题的:
Java 中很多人说不要 object.equals("test")而要"test".equals(object), 但是我一直觉得后面的写法读起来顺序很怪很反人类, 所以我宁可用 Objects.equals(obj,"test")代替, 但是其他人选择"test".equals(object)
@
git00ll 说的不清楚, 其实是一个长流程, 比如请求一个报告, 但是不会立即返回, 需要等第三方处理好, 才能拿到, 中间就每隔 1-2 分钟去轮询一次看看报告有没有好, 通常都要 10 分钟左右, 关键不是每种任务都是这样的, 如果单为它建一个线程池又感觉有点过了, 想搞个通用的解法
上面的我都研究了一下, 我这个系统比较简单, 本身就是个单体, 并不是分布式的, 这次也只是想要把这个后台任务独立出去搞多机并行, 感觉我这个还不到动用 akka/协程之类的方案的地步, 应该还是简单点, 一个简单的调度系统加动态线程池就足够了, 美团开源的那个动态线程池看上去比较适合, 我先研究一下试试看