微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何区分 jQAssistant 中的“直接”和“间接”依赖项

如何解决如何区分 jQAssistant 中的“直接”和“间接”依赖项

为了说明我的问题,我创建了 a minimal,fictional example project,它包含三个类,public static void main(String[] args) throws Throwable { File inputJarFile=new File(args[0]); File intermediateFile=new File(args[1]); List<FileData> fileDataEntries=parse(inputJarFile); write(fileDataEntries,intermediateFile); read(intermediateFile); } public static List<FileData> parse(File inputJarFile) throws IOException { List<FileData> list=new ArrayList<>(); try (JarInputStream stream=new JarInputStream(new FileInputStream(inputJarFile))) { for (ZipEntry entry; (entry=stream.getNextJarEntry()) != null;) { byte[] data=readAllBytes(stream); if (data.length > 0) { list.add(new FileData(entry.getName(),data)); } stream.closeEntry(); } } return list; } public static void write(List<FileData> fileDataEntries,File output) throws Throwable { try (DataOutputStream outputStream=new DataOutputStream(new FileOutputStream(output))) { int entryCount=fileDataEntries.size(); outputStream.writeInt(entryCount); for (FileData fileData : fileDataEntries) { int entryRealSize=fileData.getData().length; { System.out.println("Writing: " + fileData.getName() + " Length: " + entryRealSize); outputStream.writeUTF(fileData.getName()); outputStream.writeInt(entryRealSize); outputStream.write(fileData.getData()); } } outputStream.flush(); } } public static void read(File intermediateFile) throws IOException { try (DataInputStream dataInputStream=new DataInputStream(new FileInputStream(intermediateFile))) { for (int entryCount=dataInputStream.readInt(),i=0; i < entryCount; i++) { String utf=dataInputStream.readUTF(); int entrySize=dataInputStream.readInt(); System.out.println("Entry name: " + utf + " size: " + entrySize); byte[] data=readFixedLengthBuffer(dataInputStream,entrySize); System.out.println("Entry bytes length: " + data.length); } } } private static byte[] readAllBytes(InputStream input) throws IOException { byte[] buffer=new byte[4096]; byte[] total=new byte[0]; int len; do { len=input.read(buffer); if (len > 0) { byte[] total0=total; total=new byte[total0.length + len]; System.arraycopy(total0,total,total0.length); System.arraycopy(buffer,total0.length,len); } } while (len >= 0); return total; } private static byte[] readFixedLengthBuffer(InputStream input,int size) throws IOException { byte[] buffer=new byte[size]; int pos=0; int len; do { len=input.read(buffer,pos,size - pos); if (len > 0) { pos+=len; } } while (pos < size); return buffer; } private static class FileData { private final String name; private final byte[] data; public FileData(String name,byte[] data) { super(); this.name=name; this.data=data; } public String getName() { return this.name; } public byte[] getData() { return this.data; } } ServiceTransaction

Product

类型 package org.example; public class Service { public Service(Transaction transaction) { int buyerId = transaction.getProduct().getId(); } } 位于单独的包 Product

domain

为了这个例子,假设我想避免 package org.example.domain; public class Product { // [...] public int getId() { return this.id; } } 依赖包 Service 中的任何东西。

我可以使用这个查询来确保这一点:

domain

这将返回一个非空结果,即违反了约束 - 因为 jQAssistant 在这种情况下在 MATCH (c {name:"Service"})-[:DEPENDS_ON]->(d) WHERE d.fqn STARTS WITH "org.example.domain" RETURN c.fqn,d.fqn :DEPENDS_ON 之间创建了 Service 关系,这感觉违反直觉,因为在 Product 中既没有导入也没有直接引用 org.example.domain.Product

这让我想到了以下问题:

  • 这种行为是有意还是无意?
  • 有没有办法区分在父类型中导入和使用依赖项的“直接”依赖项和我的示例中所示的“间接”依赖项?

解决方法

行为是出于技术和概念层面的意图:

技术:在扫描 Java 类时,所有遇到的依赖项都会聚合。在示例中,getProduct() 返回一个 Product,该 Product 用于调用其上的方法,因此会对其进行跟踪。

概念:代码字面取决于产品。如果从类路径中删除类型,则显示的代码会中断。即使没有导入或显式字段/变量/参数/返回类型声明,依赖项仍然存在。如果您想重构(例如,将域和服务拆分为不同的工件),您还需要解决这种依赖性。所以你可以反过来看:即使你没有在代码中明确地看到依赖项,它也会被 jQA 看到。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。