缺少“框架级别”。访问修饰符 [英] The missing "framework level" access modifier

查看:100
本文介绍了缺少“框架级别”。访问修饰符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是场景。作为公开许可的开源API的创建者,我的团队创建了一个基于Java的Web用户界面框架(那么还有什么新功能?)。为了使事情保持井井有条并按Java规范进行组织,我们使用了命名约定为
org.mygroup.myframework.x的包,其中x代表组件,验证器,转换器,实用程序等(同样,还有什么新功能?)。

Here's the scenario. As a creator of publicly licensed, open source APIs, my group has created a Java-based web user interface framework (so what else is new?). To keep things nice and organized as one should in Java, we have used packages with naming convention org.mygroup.myframework.x, with the x being things like components, validators, converters, utilities, and so on (again, what else is new?).

现在,在org.mygroup.myframework.foo.Bar类中的某个地方,方法是 void doStuff() 我需要执行特定于我的框架的逻辑,并且需要能够从框架中的其他几个地方调用它,例如org.mygroup.myframework.far.Boo。鉴于Boo既不是Bar的子类,也不在Bar的完全相同的包中,因此必须将方法doStuff()声明为可被Boo调用的公共对象。

Now, somewhere in class org.mygroup.myframework.foo.Bar is a method void doStuff() that I need to perform logic specific to my framework, and I need to be able to call it from a few other places in my framework, for example org.mygroup.myframework.far.Boo. Given that Boo is neither a subclass of Bar nor in the exact same package, the method doStuff() must be declared public to be callable by Boo.

但是,我的框架存在作为一种工具,允许其他开发人员为其客户创建更简单,更优雅的RIA。但是,如果com.yourcompany.yourapplication.YourComponent调用doStuff(),则可能会产生意想不到的不良后果。我希望
永远不要允许这种情况发生。 请注意,Bar包含其他真正公开的方法。

However, my framework exists as a tool to allow other developers to create simpler more elegant R.I.A.s for their clients. But if com.yourcompany.yourapplication.YourComponent calls doStuff(), it could have unexpected and undesirable consequences. I would prefer that this never be allowed to happen. Note that Bar contains other methods that are genuinely public.

在象牙塔世界中,我们将重新编写Java语言并插入一个标记化的默认访问模拟,它将允许我们选择的包结构中的任何类访问我的方法,也许看起来类似于:

In an ivory tower world, we would re-write the Java language and insert a tokenized analogue to default access, that would allow any class in a package structure of our choice to access my method, maybe looking similar to:

[org.mygroup.myframework.*] void doStuff() { .... }

通配符意味着包以org.mygroup.myframework开头的任何类都可以调用,但没有其他人可以调用。

where the wildcard would mean any class whose package begins with org.mygroup.myframework can call, but no one else.

鉴于这个世界不存在,还有什么其他好处

Given that this world does not exist, what other good options might we have?

请注意,这是由现实情况引起的;名称已更改,以保护罪名。存在一个真实的框架,在整个Javadoc中,人们会发现注释为此方法是MYFRAMEWORK的内部方法,而不是其公共API的
的一部分。请不要打电话!!!!!的公共方法。一项小小的研究表明,这些方法是在框架中的其他位置调用的。

Note that this is motivated by a real-life scenario; names have been changed to protect the guilty. There exists a real framework where peppered throughout its Javadoc one will find public methods commented as "THIS METHOD IS INTERNAL TO MYFRAMEWORK AND NOT PART OF ITS PUBLIC API. DO NOT CALL!!!!!!" A little research shows these methods are called from elsewhere within the framework.

实际上,我是使用相关框架的开发人员。尽管我们的应用程序已经部署并且取得了成功,但我的团队遇到了许多挑战,我们希望说服老板再也不要使用此框架。我们希望对框架开发人员做出的糟糕的设计决策进行深思熟虑的呈现,而不仅仅是做大做文章。这个问题只是我们要解决的问题之一,但我们只是无法直截了当地指出自己的做事方式。我的工作场所已经进行了热烈的讨论,所以我想知道世界其他地方会怎么想。

In truth, I am a developer using the framework in question. Although our application is deployed and is a success, my team experienced so many challenges that we want to convince our bosses to never use this framework again. We want to do this in a well thought out presentation of the poor design decisions made by the framework's developers, and not just as a rant. This issue would be one (of several) of our points, but we just can't put a finger on how we might have done it differently. There has already been some lively discussion here at my workplace, so I wondered what the rest of the world would think.

更新:到目前为止,对这两个答复者都没有冒犯,但我认为您错过了分数,或者我表达得不好。任一种方式都可以让我尝试阐明事物。简而言之,该框架的开发人员应如何重构以下内容。注意,这是一个非常粗糙的例子。

Update: No offense to the two answerers so far, but I think you've missed the mark, or I didn't express it well. Either way allow me to try to illuminate things. Put as simply as I can, how should the framework's developers have refactored the following. Note this is a really rough example.

package org.mygroup.myframework.foo;
public class Bar {
     /** Adds a Bar component to application UI */
     public boolean addComponentHTML() {
         // Code that adds the HTML for a Bar component to a UI screen
         // returns true if successful
         // I need users of my framework to be able to call this method, so
         // they can actually add a Bar component to their application's UI
     }

     /** Not really public, do not call */
     public void doStuff() {
         // Code that performs internal logic to my framework
         // If other users call it, Really Bad Things could happen!
         // But I need it to be public so org.mygroup.myframework.far.Boo can call
     }
}






另一个更新:因此,我刚刚了解到C#具有内部访问修饰符。因此,表达这个问题的更好方法可能是如何在Java中模拟/仿真内部访问?尽管如此,我并没有寻找新的答案。我们的老板最终同意了上面提到的问题


Another update: So I just learned that C# has the "internal" access modifier. So perhaps a better way to have phrased this question might have been, "How to simulate/ emulate internal access in Java?" Nevertheless, I am not in search of new answers. Our boss ultimately agreed with the concerns mentioned above

推荐答案

在提到文档问题时,您离答案很近。真正的问题不是您无法保护内部方法;而是相反,内部方法会污染您的文档,并带来客户机模块可能错误地调用内部方法的风险。

You get closest to the answer when you mention the documentation problem. The real issue isn't that you can't "protect" your internal methods; rather, it is that the internal methods pollute your documentation and introduce the risk that a client module may call an internal method by mistake.

当然,即使您确实有细粒度的权限,您仍然无法阻止客户端模块调用内部方法-jvm仍然无法防止基于反射的私有方法调用。

Of course, even if you did have fine grained permissions, you still aren't going to be able to prevent a client module from calling internal methods---the jvm doesn't protect against reflection based calls to private methods anyway.

我使用的方法是为每个有问题的类定义一个接口,并让该类实现它。可以仅根据客户端模块来记录该接口,而实现类可以提供所需的内部文档。如果不想的话,甚至不需要在分发包中包含实现javadoc,但是无论哪种方式,都清楚地划定了边界。

The approach I use is to define an interface for each problematic class, and have the class implement it. The interface can be documented solely in terms of client modules, while the implementing class can provide what internal documentation you desire. You don't even have to include the implementation javadoc in your distribution bundle if you don't want to, but either way the boundary is clearly demarcated.

只要您可以确保在运行时每个文档界面仅加载一个实现,现代的jvm将确保您不会因使用它而遭受任何性能损失;并且,您可以在测试期间加载线束/存根版本,以获得额外的奖励。

As long as you ensure that at runtime only one implementation is loaded per documentation-interface, a modern jvm will guarantee you don't suffer any performance penalty for using it; and, you can load harness/stub versions during testing for an added bonus.

这篇关于缺少“框架级别”。访问修饰符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆