范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

聊聊软件开发的SLAP原则

  序
  本文主要研究一下软件开发的SLAP(Single Level of Abstraction Principle)原则 SLAP
  SALP即Single Level of Abstraction Principle的缩写,即单一抽象层次原则。 在Robert C. Martin的<>一书中的函数章节有提到:
  要确保函数只做一件事,函数中的语句都要在同一抽象层级上。函数中混杂不同抽象层级,往往让人迷惑。读者可能无法判断某个表达式是基础概念还是细节。更恶劣的是,就像破损的窗户,一旦细节与基础概念混杂,更多的细节就会在函数中纠结起来。
  这与  Don"t Make Me Think[1]  有异曲同工之妙,遵循SLAP的代码通常阅读起来不会太费劲。
  另外没有循序这个原则的通常是 Leaky Abstraction[2]
  要遵循这个原则通常有两个好用的手段便是抽取方法与抽取类。 实例1public List buildResult(Set resultSet) {     List result = new ArrayList<>();     for (ResultEntity entity : resultSet) {         ResultDto dto = new ResultDto();         dto.setShoeSize(entity.getShoeSize());                 dto.setNumberOfEarthWorms(entity.getNumberOfEarthWorms());         dto.setAge(computeAge(entity.getBirthday()));         result.add(dto);     }     return result; }
  这段代码包含两个抽象层次,一个是循环将resultSet转为  List  ,一个是转换ResultEntity到ResultDto
  可以进一步抽取转换ResultDto的逻辑到新的方法中 public List buildResult(Set resultSet) {     List result = new ArrayList<>();     for (ResultEntity entity : resultSet) {         result.add(toDto(entity));     }     return result; }  private ResultDto toDto(ResultEntity entity) {     ResultDto dto = new ResultDto();     dto.setShoeSize(entity.getShoeSize());             dto.setNumberOfEarthWorms(entity.getNumberOfEarthWorms());     dto.setAge(computeAge(entity.getBirthday()));     return dto; }
  这样重构之后,buildResult就很清晰  实例2public MarkdownPost(Resource resource) {         try {             this.parsedResource = parse(resource);             this.metadata = extractMetadata(parsedResource);             this.url = "/" + resource.getFilename().replace(EXTENSION, "");         } catch (IOException e) {             throw new RuntimeException(e);         }     }
  这里的url的拼装逻辑与其他几个方法不在一个层次,重构如下  public MarkdownPost(Resource resource) {         try {             this.parsedResource = parse(resource);             this.metadata = extractMetadata(parsedResource);             this.url = urlFor(resource);         } catch (IOException e) {             throw new RuntimeException(e);         } }  private String urlFor(Resource resource) {         return "/" + resource.getFilename().replace(EXTENSION, ""); }实例3public class UglyMoneyTransferService  {     public void transferFunds(Account source,                                Account target,                                BigDecimal amount,                                boolean allowDuplicateTxn)                           throws IllegalArgumentException, RuntimeException      {         Connection conn = null;     try {         conn = DBUtils.getConnection();         PreparedStatement pstmt =              conn.prepareStatement("Select * from accounts where acno = ?");         pstmt.setString(1, source.getAcno());         ResultSet rs = pstmt.executeQuery();         Account sourceAccount = null;         if(rs.next()) {             sourceAccount = new Account();             //populate account properties from ResultSet         }         if(sourceAccount == null){             throw new IllegalArgumentException("Invalid Source ACNO");         }         Account targetAccount = null;         pstmt.setString(1, target.getAcno());         rs = pstmt.executeQuery();         if(rs.next()) {             targetAccount = new Account();             //populate account properties from ResultSet         }         if(targetAccount == null){             throw new IllegalArgumentException("Invalid Target ACNO");         }         if(!sourceAccount.isOverdraftAllowed()) {             if((sourceAccount.getBalance() - amount) < 0) {                 throw new RuntimeException("Insufficient Balance");             }         }         else {             if(((sourceAccount.getBalance()+sourceAccount.getOverdraftLimit()) - amount) < 0) {                 throw new RuntimeException("Insufficient Balance, Exceeding Overdraft Limit");             }         }         AccountTransaction lastTxn = .. ; //JDBC code to obtain last transaction of sourceAccount         if(lastTxn != null) {             if(lastTxn.getTargetAcno().equals(targetAccount.getAcno()) && lastTxn.getAmount() == amount && !allowDuplicateTxn) {             throw new RuntimeException("Duplicate transaction exception");//ask for confirmation and proceed             }         }         sourceAccount.debit(amount);         targetAccount.credit(amount);         TransactionService.saveTransaction(source, target,  amount);     }     catch(Exception e){         logger.error("",e);     }     finally {         try {              conn.close();          }          catch(Exception e){              //Not everything is in your control..sometimes we have to believe in GOD/JamesGosling and proceed         }     } }     }
  这段代码把dao的逻辑泄露到了service中,另外校验的逻辑也与核心业务逻辑耦合在一起,看起来有点费劲,按SLAP原则重构如下  class FundTransferTxn {     private Account sourceAccount;      private Account targetAccount;     private BigDecimal amount;     private boolean allowDuplicateTxn;     //setters & getters }  public class CleanMoneyTransferService  {     public void transferFunds(FundTransferTxn txn) {         Account sourceAccount = validateAndGetAccount(txn.getSourceAccount().getAcno());         Account targetAccount = validateAndGetAccount(txn.getTargetAccount().getAcno());         checkForOverdraft(sourceAccount, txn.getAmount());         checkForDuplicateTransaction(txn);         makeTransfer(sourceAccount, targetAccount, txn.getAmount());     }      private Account validateAndGetAccount(String acno){         Account account = AccountDAO.getAccount(acno);         if(account == null){             throw new InvalidAccountException("Invalid ACNO :"+acno);         }         return account;     }      private void checkForOverdraft(Account account, BigDecimal amount){         if(!account.isOverdraftAllowed()){             if((account.getBalance() - amount) < 0)    {                 throw new InsufficientBalanceException("Insufficient Balance");             }         }         else{             if(((account.getBalance()+account.getOverdraftLimit()) - amount) < 0){                 throw new ExceedingOverdraftLimitException("Insufficient Balance, Exceeding Overdraft Limit");             }         }     }      private void checkForDuplicateTransaction(FundTransferTxn txn){         AccountTransaction lastTxn = TransactionDAO.getLastTransaction(txn.getSourceAccount().getAcno());         if(lastTxn != null)    {             if(lastTxn.getTargetAcno().equals(txn.getTargetAccount().getAcno())                      && lastTxn.getAmount() == txn.getAmount()                      && !txn.isAllowDuplicateTxn())    {                 throw new DuplicateTransactionException("Duplicate transaction exception");             }         }     }      private void makeTransfer(Account source, Account target, BigDecimal amount){         sourceAccount.debit(amount);         targetAccount.credit(amount);         TransactionService.saveTransaction(source, target,  amount);     }     }
  重构之后transferFunds的逻辑就很清晰,先是校验账户,再校验是否超额,再校验是否重复转账,最后执行核心的makeTransfer逻辑  小结
  SLAP与  Don"t Make Me Think[3]  有异曲同工之妙,遵循SLAP的代码通常阅读起来不会太费劲。另外没有循序这个原则的通常是Leaky Abstraction[4] 。doc
  • Clean Code - Single Level Of Abstraction[5]
  • Clean Code: Don’t mix different levels of abstractions[6]
  • Single Level of Abstraction (SLA)[7]
  • The Single Level of Abstraction Principle[8]
  • SLAP Your Methods and Don"t Make Me Think![9]
  • Levels of Abstraction[10]
  • Maintain a Single Layer of Abstraction at a Time | Object-Oriented Design Principles w/ TypeScript[11]
  • 聊一聊SLAP:单一抽象层级原则[12]
  外部链接
  [1]  Don"t Make Me Think   https://book.douban.com/subject/1440223/
  [2]  Leaky Abstraction   https://khalilstemmler.com/wiki/leaky-abstraction/
  [3]  Don"t Make Me Think   https://book.douban.com/subject/1440223/
  [4]  Leaky Abstraction   https://khalilstemmler.com/wiki/leaky-abstraction/
  [5]  Clean Code - Single Level Of Abstraction   https://www.c-sharpcorner.com/article/clean-code-single-level-of-abstraction/
  [6]  Clean Code: Don’t mix different levels of abstractions   https://www.sivalabs.in/2013/12/clean-code-dont-mix-different-levels-of-abstractions/
  [7]  Single Level of Abstraction (SLA)   http://principles-wiki.net/principles:single_level_of_abstraction
  [8]  The Single Level of Abstraction Principle   https://dzone.com/articles/the-single-level-of-abstraction-principle
  [9]  SLAP Your Methods and Don"t Make Me Think!   https://dzone.com/articles/slap-your-methods-and-dont-make-me-think
  [10]  Levels of Abstraction   https://dzone.com/articles/levels-of-abstraction
  [11]  Maintain a Single Layer of Abstraction at a Time | Object-Oriented Design Principles w/ TypeScript   https://khalilstemmler.com/articles/oop-design-principles/maintain-a-single-layer-of-abstraction/
  [12]  聊一聊SLAP:单一抽象层级原则   https://droidyue.com/blog/2019/03/17/slap-single-level-of-abstraction-principle/

如果祖国有那么一天,我们是否做好了准备?一场俄乌战争,大公司争相选边站队,而他们的产品在我们生活中无处不在,制裁是一个国家,却与每个人每个家庭息息相关。如果祖国也有那么一天,我们是否做好了准备?!!!1苹果限制支付功能,百度爱奇艺等公司被美列入预摘牌名单,中国证监会回应了美东时间3月30日,美国证券交易委员会将百度富途控股爱奇艺聚焦血液肿瘤的凯信远达医药和从事渔业养殖的Nocera加入预摘牌名单。根据SEC的说法,这五家公司需要于4月20日前向SE国家为什么要大力推广新能源汽车国家近年来大力扶持推广新能源车,补贴,免购置税等等手段层出不穷。其中是有非常多的长远规划与考虑的。今天笔者就略说一二。1能源中国是世界上最大的石油进口国。作为世界最大的工业出口国与(法治)浙江整治虚拟货币挖矿设备企业参与且情节严重的可停业或关闭新华社杭州3月31日电(记者岳德亮)为了有效防范虚拟货币挖矿活动盲目无序发展带来的风险隐患,浙江省发展改革委省司法厅近日决定整治虚拟货币挖矿设备,以重点突破带动整体推进。挖矿设备一紫光6nm芯片传来好消息!国产芯片又进一步突破自从芯片市场出现紧缺情况,我国各企业就开始发力,紫光展锐是国内领先的芯片设计巨头,目前已经实现了6nm芯片的稳定量产,经过自主研发,为国产厂商提供了不俗的芯片产品。大部分人还是比较工信部12月份我国手机产量2。1亿台,同比减少3。5IT之家3月31日消息,昨日,工业和信息化部公布了2022年12月份电子信息制造业运行情况。12月份,我国电子信息制造业生产保持两位数增长出口交货值延续增长态势营业收入增速小幅下降孟晚舟回国后首次亮相!华为发布会看全球化企业的战略选择我这次到深圳来参加了华为业绩年报的发布会。28号下午的发布会非常的隆重,华为的轮值董事长郭平和副董事长财务总监CFO全球瞩目的风云人物孟晚舟出席。线上线下吸引了大量的中外媒体各界的华为P50Pro全球发布,国外资深技术编辑却认为,迟到总比没有强华为P50Pro终于走向全球,拥有全新的设计多功能相机以及独特的硬件和软件,这本是振奋国人的好消息,但是资深的技术编辑亚历克斯沃克托德对华为P50Pro的发布,有着自己独特的见解迟美国ITC正式对功率半导体以及包含该功率半导体的移动设备和计算机启动337调查美国ITC正式对功率半导体以及包含该功率半导体的移动设备和计算机启动337调查财联社3月29日电,中国贸易救济信息网消息,3月28日,美国国际贸易委员会(ITC)投票决定对特定功率一图读懂BC科技集团(00863。HK)2021年全年业绩,数字资产平台全球规模化扩张3月29日,BC科技集团(00863。HK)发布截至2021年12月31日止年度业绩,报告期内,集团录得总收益及收入为3。52亿港元,较2020财政年度2。43亿港元,增加约44。阿里巴巴真的能反弹吗?阿里马云,中国互联网企业,交税,捐款,科技创新,解决社会就业,互联网企业第一名,给国家社会贡献最大的,电商保持营利交税第一,阿里的基本面很好,如果没有社会抹黑负面影响会更好,阿里,
吃鸡神器北通E1手游键鼠转换器,让中年大叔充当和平精英80年代初生人,应该是最早接触电子游戏的一代,那时的社会舆论将电子游戏喻为洪水猛兽,大有将我们那一代人弄垮的论调,但舆论和爸妈丝毫没有阻挡我们在红白机上鏖战在街机厅里驻足,还好后来长安汽车又放大招!超集电驱超高效率碾压一众热门新能源车型8月24日,长安汽车在首届开放共赢融合创新科技生态大会上疯狂秀肌肉,除了发布新汽车新生态全新战略,承载着长安汽车在电车领域黑科技成果的首款战略车型C385同样值得关注。活动现场,长裸车预算20万左右,6款热门SUV选择优劣分析最近,20万元裸车预算买什么SUV更好的话题受到了很多人的关注,实际上,当预算来到这个价格区隔,消费者的选择确实变得非常多,例如合资品牌紧凑型SUV(入门版车型)部分纯电动SUV(新款哈弗H9或本月10日上市?外型粗狂像大叔,疑似售价20。98万起本次的成都车展,发现了一辆外观改动不小的车型,它就是新款的哈弗H9,尤其是前脸,就像一个外表粗狂的大叔,而且新款哈弗H9,或将在本月10日上市,不少人猜测售价区间为20。9827。快手一哥复出当天,道路被封不让过,回应来了大家好,我是大叔。快手一哥大家都不陌生吧,在快手平台上拥有八千多万的粉丝,在经历售假风波,消失一百多天后,他又高调复出了。3月27日中午复出首秀,首播长达13个小时,辛巴累计卖出1苹果警告腾讯字节限时整改,否则将被下架大家好,我是大叔。关于隐私问题近期大叔和大家聊了好多。其实说实话在现代社会,隐私几乎不存在了,互联网了解你说不定都比父母了解的多。你想买什么,喜欢吃什么,喜欢什么娱乐,互联网都知道苹果再曝9月发布会新品!比iPhone13更吸引人苹果9月份新品发布会召开在即,而其中最让人关注的新一代iPhone13系列,鸭鸭之前已经写很多了,今天就不再赘述了。如果你到现在还来问我十三到底香不香?我只能说别问,问就是假粉丝!可怕!私密生活曝光,大量偷窥视频流出大家好,我是大叔。说实话,大叔一直觉得偷窥,针孔摄像头离自己的生活很远。平常刷到的一些视频也当作是危言耸听,小题大作,从来没当一回事。这样说来,大叔这个脑回路,估计要被小伙伴骂了。得物与唯品会就假货互掐,小丑到底是谁大家好,我是大叔。最近有小伙伴问大叔说想买一个国际大牌的包送给自己妈妈当生日礼物,除了官网还有哪里的包是正品稍微便宜点的?这可真是问到大叔了,大叔作为一个小小的互联网人,看到了太多网红狗头萝莉大尺度曝光!不作就不会死大家好,我是大叔。抖音网红狗头萝莉想必喜欢刷视频的小伙伴,应该都刷到过她吧,作为二次元活动的常驻cosplayer,在抖音上号称是万千宅男的梦,不少宅男心中的老婆。之前是一个游戏平三款家用空气炸锅,这么选择空气炸锅让你不踩坑,一次到位前言大家好,我是小猴。喜爱油炸食品的你是不是每次吃完之后都充满了罪恶感,看看日益变大的肚子和跑几步就喘气的体能,总想着享受美食的同时能够吃的更加健康。因此根据这种需求,家电品牌从中