“Complexity kills. It sucks the life out of developers, It makes products difficult to plan, build and test.”Complexity kills. It kills developers and makes products hard to plan, build, and test)

How do you build a city

  • 1. Every city has a group of people who manage different parts of it, with some taking care of the big picture and others taking care of the details

  • 2. Deepen the appropriate levels of abstraction and modules so that individuals and the “components” they manage can function effectively even without understanding the big picture

2. Separate system construction from use

  • 1. Construction and use are very different processes

  • 2. The software system should separate the startup process from the run time logic after the startup process, and there will be entangled dependencies in the construction of application objects during the startup process

  • 3. One way to separate construction from use is to move the entire construction process into main, or a module called Main, and design the rest of the system assuming that all objects are correctly constructed and set up

  • 4. The abstract factory pattern can be used to give the application control over when objects are created, but the details of construction are isolated from the application code

  • 5. Inversion of control follows the principle of single responsibility by taking the second responsibility out of an object and transferring it to another object that focuses on it. In the dependency management scenario, the object should not be responsible for materializing its dependence on itself, instead, it should transfer this power and responsibility to other “powerful” mechanisms, so as to realize the reversal of control

Jndi lookups are a partial implementation of DI, in which an object requests a directory server to provide a “service” that matches a particular name.

Benefits of delayed initialization:

  • Most DI containers do not construct objects until they are needed,
  • Second, many of these containers provide mechanisms for invoking factories or proxies, which can be used for lazy assignment or similar optimization processes

Expansion and 3.

  • 1. “Getting the system right from the beginning” is a myth. Instead, we should implement the user story today, refactor it, and expand the system tomorrow to implement a new user story. Test-driven development, refactoring, and the clean code they produce ensure this process at the code level

  • 2. Software systems are analogous to physical systems. Their architectures can grow incrementally, as long as we continue to slice and dice our concerns appropriately

Cross-type concern:

  • In principle, the persistence strategy can be inferred from the perspective of module and encapsulation. In practice, however, the code that implements the persistence strategy has to be spread across many objects, which is the cross-cutting concern
  • In fact, the EJB architecture in persistence, security and affairs method is “expected” aspect oriented programming, and Aop is a recovery across type universal means of modularization, a focus in Aop, known as the module structure indicates the behavior of the system in which point will be modified in a consistent way, to support a particular scenario. This specification is implemented using some neat declarative or programming mechanism.

In the case of persistence, you can declare which objects and properties (or their schemas) should be persisted, and then delegate the persistence task to the persistence framework. Behavior modification is done in object code in a nondestructive manner by the AOP framework.

4. The Java proxy

  • 1. Suitable for simple cases, such as wrapping method calls in separate objects or classes. However, dynamic proxies provided by the JDK only work with interfaces. For proxy classes, you’ll use bytecode manipulation libraries such as CGLIB, ASM, or Javassist.

Code volume and complexity are two big weaknesses of agents, making it difficult to create clean code.

Here’s an example: == Even for this simple example, there is a lot of relatively complex code ==.

5. Pure Java AOP framework

Fortunately, most agent template code is handled automatically by programming tools. In several Java frameworks, such as Spring AOP and JBoss AOP, proxies are embedded to enable aspect-oriented programming from pure Java code. In Spring, you code your business logic as old-fashioned Java AOP objects. ==POJO (Plain Ordinary Java Object) Self-cleaning, not dependent on the enterprise framework (or other domains). Therefore, it is conceptually simpler and more test-driven. The relative simplicity also makes it easier to ensure that appropriate user stories are implemented correctly, and to maintain and improve the code for future user stories.

Using descriptive profiles or apis, you put together the required application architecture, including persistence, transactions, security, caching, recovery, and cross-cutting issues. In many cases, you’re really just specifying Sprint or Jboss class libraries, and the framework handles the mechanism of using Java proxies or bytecode libraries in a transparent way to the user. These declarations drive the dependency injection (DI) container, which then materializes the main objects and concatenates them as needed.

6. The AspectJ aspects

The most full-featured tool for faceted concern sharding through aspects is the AspectJ language, a Java extension that provides “first-class” support for handling aspects as module constructs. Pure Java implementations provided by Spring AOP and JBoss AOP are sufficient for 80-90 percent of aspects.

The downside of AspectJ, however, is that it requires several new tools to learn how new languages are constructed and used.

7. Test drive system architecture

  • 1. The power of segmenting aspects of concern through AOP should not be underestimated. If you can write your application’s domain logic with POJOs, separate the code level from the architectural focus, you can really drive the architecture with tests.

  • 2. There is no need to make Big Design Up Front (BDUF). BDUF can even be harmful.

  • 3. We can start software projects with a “simple and natural” but well-segmented architecture, deliver working user stories quickly, and add more infrastructure as we grow in scale.

  • 4. The best system architecture consists of modular areas of concern, each implemented using pure Java (or other language) objects, integrated between the different areas using the least invasive aspect or aspect like tools, and is test-driven, just like code.

8. Optimize your decisions

  • 1. Modularity and focus segmentation make decentralized management and decision-making possible.

  • 2. Delaying decisions until the last minute is also good because it allows us to make choices based on the best possible information. If the decision is made too early, there will be too little customer feedback, thought about the project, and experience in implementing it.

  • 3. The agility provided by POJO systems with modular concerns allows us to make optimized, well-timed decisions based on the latest knowledge, with reduced complexity.

9. Judicious use adds demonstrable value to criteria

Standards make it easier to reuse ideas and components, hire people with relevant experience, encapsulate good ideas, and connect components together. However, the process of creating standards sometimes takes too long for the industry to wait, and some standards fail to align with the real needs of the adopters they are meant to serve.

10. Systems require domain-specific languages

  • 1. A Domain-specific Language (DSL) is a separate small scripting Language or API written in a standard Language that Domain experts can use to write code that reads like well-organized prose

  • 2. Domain-specific languages allow all levels of abstraction and all domains in an application, from high-level policies to low-level details, to be expressed using POJOs

  • 3. DSLS, when used effectively, raise the level of abstraction above code idiomatic and design patterns. It allows developers to get right to the original intent of the code at the right level of abstraction.

11. A summary:

This chapter mainly tells about the system neat, to achieve the system neat, need to pay attention to the module function division, pay attention to the simple Been object is not coupled with the business logic together, do a single responsibility.

At the initial stage of the project, all aspects of the future system will be considered. It is unnecessary to provide a lot of APIS or function points that are not required at present. What we need to do is to divide each function module well, and pay attention to the scalability and isolation of each module. This is convenient for continuous expansion and reconstruction optimization, rapid iterative and agile development.

12. Example:

The separation of construction and use will reduce the coupling degree between classes, which is convenient for the subsequent implementation of replacement modification. Here’s a relatively simple example:

	public class HandlerImpl {
        public void handler(a) {
              Component component= newcomponent(); component.handle(); }}Copy the code

In this case, since there is no separation between construction and usage, i.e. the HandlerImpl is both the constructor of the Component (which calls the constructor) and the executor of the Component (which calls the method), it is assumed that the implementation of the Component needs to be replaced with an interface implementation class, or some other class. It’s going to cause a lot of places like this in the whole system to have to be replaced by theta

 Component component= newComponentImpl (); Component2 component=new Component2();
Copy the code

This modification is too much, the coupling degree is too high, affecting subsequent maintenance. Similar to “separate build and use” can be used with similar factory pattern + interface oriented programming, such as:

	 public class HandlerImpl {
                public void handler(a) { Component component= ComponentFactory.getComponent(); component.handle(); }}public class ComponentFactory {
                public static Component getComponent(a) {
                    Component component= new componentImpl1();
                    return; }}Copy the code

To replace the Component implementation later, or to add a Component conditional, you only need to modify the constructor ComponentFactory without changing everything: ComponentFactory (ComponentFactory); ComponentFactory (ComponentFactory);

 		public class ComponentFactory {
                public static Component getComponent(a) {
                    if(...). {return new componentImpl1(); 
                    }
                    if(...). {return newcomponentImpl2(); }}}Copy the code

13. References

The way of clean code daimajiaoliu.com/daima/4edf2… www.jianshu.com/p/c44eca6ad… Juejin. Cn/post / 684490… Blog.csdn.net/pengbo66656…

Pay attention to the public account “Programmer interview”

Reply to “interview” to get interview package!!

This public account to share their own from programmer xiao Bai to experience spring recruitment autumn recruitment cut more than 10 offer interview written test experience, including [Java], [operating system], [computer network], [design mode], [data structure and algorithm], [Dacheng face by], [database] look forward to you join!!

1. Computer network —- Three times shake hands four times wave hands

2. Dream come true —– Project self-introduction

Here are the design patterns you asked for

4. Shocked! Check out this programmer interview manual!!

5. Teach you the interview “Profile” word for word

6. Nearly 30 interviews shared