1. Algorithm 一道算法题
本周算法题为二叉树最大路径和
本题的重点是当左右小于 0 时,当做 0 来处理,这样能减少很多边界值处理逻辑
2. Review 阅读一篇英文文章
本周继续阅读 MF 的# Inversion of Control Containers and the Dependency Injection pattern,本周终于将文章阅读完毕
Code or configuration files
A separate but often conflated issue is whether to use configuration files or code on an API to wire up services. For most applications that are likely to be deployed in many places, a separate configuration file usually makes most sense. Almost all the time this will be an XML file, and this makes sense. However there are cases where it's easier to use program code to do the assembly. One case is where you have a simple application that's not got a lot of deployment variation. In this case a bit of code can be clearer than a separate XML file.
使用配置文件还是代码来连接服务是一个既独立又常常混淆的问题。对于大多数可能部署在多个地方的应用程序来说,使用一个单独的配置文件通常是最合理的选择。几乎所有情况下,这将是一个XML文件,这样做十分合理。然而,在某些情况下,使用程序代码来进行组装更加简单。一个例子是当你有一个简单的应用程序,部署变化不大时。在这种情况下,使用一些代码可能比一个独立的XML文件更清晰明了。
A contrasting case is where the assembly is quite complex, involving conditional steps. Once you start getting close to programming language then XML starts breaking down and it's better to use a real language that has all the syntax to write a clear program. You then write a builder class that does the assembly. If you have distinct builder scenarios you can provide several builder classes and use a simple configuration file to select between them.
一个对比的情况是组装过程非常复杂,涉及到条件步骤。一旦你开始接近编程语言的范畴,XML就会变得不够用,最好使用一个真正的语言,具备编写清晰程序的所有语法。然后,你可以编写一个构建器类来进行组装。如果你有不同的构建场景,你可以提供几个构建器类,并使用一个简单的配置文件来选择它们之间的区别。
I often think that people are over-eager to define configuration files. Often a programming language makes a straightforward and powerful configuration mechanism. Modern languages can easily compile small assemblers that can be used to assemble plugins for larger systems. If compilation is a pain, then there are scripting languages that can work well also.
我常常觉得人们过于热衷于定义配置文件。通常情况下,编程语言本身就具备了一个简单而强大的配置机制。现代语言可以轻松编译小型汇编器,用来为较大的系统组装插件。如果编译是个麻烦,那么也可以使用脚本语言来很好地完成任务。
It's often said that configuration files shouldn't use a programing language because they need to be edited by non-programmers. But how often is this the case? Do people really expect non-programmers to alter the transaction isolation levels of a complex server-side application? Non-language configuration files work well only to the extent they are simple. If they become complex then it's time to think about using a proper programming language.
常常有人说配置文件不应该使用编程语言,因为需要非程序员来编辑。但这种情况有多频繁呢?人们真的希望非程序员修改复杂的服务器端应用的事务隔离级别吗?非语言配置文件只有在简单的情况下才能很好地运作。一旦它们变得复杂,那就是考虑使用合适的编程语言的时候了。
One thing we're seeing in the Java world at the moment is a cacophony of configuration files, where every component has its own configuration files which are different to everyone else's. If you use a dozen of these components, you can easily end up with a dozen configuration files to keep in sync.
目前在Java世界中,我们正在看到一种非常杂乱的配置文件情况,每个组件都有自己独特的配置文件,与其他人的配置文件也不同。如果你使用了十几个这样的组件,很容易就会出现十几个需要保持同步的配置文件。
My advice here is to always provide a way to do all configuration easily with a programmatic interface, and then treat a separate configuration file as an optional feature. You can easily build configuration file handling to use the programmatic interface. If you are writing a component you then leave it up to your user whether to use the programmatic interface, your configuration file format, or to write their own custom configuration file format and tie it into the programmatic interface
我的建议是始终提供一种使用编程接口轻松进行所有配置的方式,然后将单独的配置文件视为一个可选功能。你可以轻松地构建配置文件处理来使用编程接口。如果你正在编写一个组件,那么就将它的使用方式留给用户决定,可以使用编程接口,你的配置文件格式,或者编写他们自己的自定义配置文件格式并将其与编程接口连接起来。
Separating Configuration from Use
The important issue in all of this is to ensure that the configuration of services is separated from their use. Indeed this is a fundamental design principle that sits with the separation of interfaces from implementation. It's something we see within an object-oriented program when conditional logic decides which class to instantiate, and then future evaluations of that conditional are done through polymorphism rather than through duplicated conditional code.
在这一切中,重要的问题是确保服务的配置与使用分离。事实上,这是一个基本的设计原则,与接口与实现的分离相一致。这是在面向对象程序中我们看到的情况,当条件逻辑决定实例化哪个类时,以及对该条件的未来评估通过多态性而不是重复的条件代码进行。
If this separation is useful within a single code base, it's especially vital when you're using foreign elements such as components and services. The first question is whether you wish to defer the choice of implementation class to particular deployments. If so you need to use some implementation of plugin. Once you are using plugins then it's essential that the assembly of the plugins is done separately from the rest of the application so that you can substitute different configurations easily for different deployments. How you achieve this is secondary. This configuration mechanism can either configure a service locator, or use injection to configure objects directly.
如果这种分离在单个代码库中很有用,当你使用组件和服务等外部元素时,它就更加重要了。首先要问的问题是,是否希望将实现类的选择推迟到特定的部署中。如果是这样,你需要使用某种插件的实现。一旦你开始使用插件,就必须将插件的组装与应用程序的其余部分分开进行,这样你就可以轻松地针对不同的部署替换不同的配置。如何实现这一点是次要的。这个配置机制可以配置一个服务定位器,或者直接使用注入来配置对象。
Some further issues
In this article, I've concentrated on the basic issues of service configuration using Dependency Injection and Service Locator. There are some more topics that play into this which also deserve attention, but I haven't had time yet to dig into. In particular there is the issue of life-cycle behavior. Some components have distinct life-cycle events: stop and starts for instance. Another issue is the growing interest in using aspect oriented ideas with these containers. Although I haven't considered this material in the article at the moment, I do hope to write more about this either by extending this article or by writing another.
在这篇文章中,我集中讨论了使用依赖注入和服务定位器的服务配置的基本问题。还有一些其他的主题也涉及到这一点,同样值得关注,但我还没有时间深入研究。特别是生命周期行为的问题。一些组件具有明显的生命周期事件,例如停止和启动。另一个问题是越来越多地使用面向方面的思想与这些容器结合。虽然我暂时没有在文章中考虑这些材料,但我希望能够通过扩展这篇文章或撰写另一篇文章来对这个问题进行更多的研究和探讨。
You can find out a lot more about these ideas by looking at the web sites devoted to the lightweight containers. Surfing from the picocontainer and spring web sites will lead to you into much more discussion of these issues and a start on some of the further issues.
您可以通过访问专注于轻量级容器的网站了解更多关于这些想法的信息。从 picocontainer 和 spring 网站浏览将会带您进入更多关于这些问题的讨论,并开始探讨一些进一步的问题。
Concluding Thoughts
The current rush of lightweight containers all have a common underlying pattern to how they do service assembly - the dependency injector pattern. Dependency Injection is a useful alternative to Service Locator. When building application classes the two are roughly equivalent, but I think Service Locator has a slight edge due to its more straightforward behavior. However if you are building classes to be used in multiple applications then Dependency Injection is a better choice.
当前的轻量级容器在服务组装方面都有一个共同的基本模式 - 依赖注入模式。依赖注入是服务定位器的一个有用替代方案。在构建应用程序类时,这两种方法几乎是等效的,但我认为服务定位器由于其更直接的行为有些优势。然而,如果您正在构建要在多个应用程序中使用的类,则依赖注入是更好的选择。
If you use Dependency Injection there are a number of styles to choose between. I would suggest you follow constructor injection unless you run into one of the specific problems with that approach, in which case switch to setter injection. If you are choosing to build or obtain a container, look for one that supports both constructor and setter injection.
如果您使用依赖注入,有几种风格可供选择。我建议您首先使用构造函数注入,除非遇到特定的问题,如遇到问题则切换到设置器注入。如果您选择构建或获取一个容器,请选择同时支持构造函数和设置器注入的容器。
The choice between Service Locator and Dependency Injection is less important than the principle of separating service configuration from the use of services within an application.
在将服务配置与应用程序中的服务使用分开的原则下,服务定位器和依赖注入之间的选择并不重要。
3. Techniques/Tips 分享一个小技巧
本周在工作中发现一个循环依赖的问题,本来认为 Spring 是能解决这个问题,但是最后发现由于 bean 被代理了,导致 spring 三级缓存无法解决这种被代理后的循环依赖,解决办法主要有三种:
- 对注入的有循环依赖的 bean,加上 @Lazy 注解
- 不要使用会产生代理的注解,像我们的项目中就是 @Repository 注解产生了动态代理导致的问题
- 彻底解决循环依赖(这是最靠谱的办法)
4. Share 分享一个观点
任何时候开始都不算晚,每天进步一点点,日积月累就是巨大的能量,现在每天刷两道题,发现对算法题没有畏惧心理了,以前对算法题怕的要死,从 8 月 20 号到现在,刷了 85 道题后,看到算法题不会心慌了,并且在刷题过程中会用到很多平时编码不怎么使用的 api,对语言的掌握也有了很大的进步