📜 ⬆️ ⬇️

Small architecture


I want to become a software architect:


This is a good target for the developer.


I want to manage the team and make important decisions about databases, frameworks and web services and all that.


Hm Well, then you don’t want to be a software architect at all.


Of course I want! I want to be the person who makes all the important decisions.


This is good, but you have not listed important decisions. You listed solutions that do not play a special role.


In the sense of? Database is not an important decision? Do you know how much money we spend on them?


Most likely too much. And no, the database is not one of the most important decisions.


How can you say that? The database is located in the very center of the system! All data is collected there, they are sorted, indexed and accessed. Without it, there will be no system!


A database is just an I / O device. It so happens that it provides some useful sorting tools, queries and reports, but these are all supporting aspects within the system architecture.


Auxiliary? This is madness.


Yes, auxiliary. Your system's business rules may use some of these tools. But they are not essential for business rules. If necessary, you can replace these tools with other tools, but the business rules will remain the same.


Well, yes, but you have to rewrite all the code, because it uses the tools of the original database.


Well, that's your problem.


What do you mean?


Your problem is that you believe that business rules depend on database tools. This is not true. In any case, they should not depend on if you have developed a good architecture.


This is madness. How can I create business rules that do not use the tools I need to use?


I did not say that they do not use database tools. I said that they should not depend on them. Business rules should not know which particular database you are using.


How to make business rules use tools without knowing what the tools are?


Need to invert the dependency. Your database depends on business rules. Make it so that business rules do not depend on the base.


You say some rubbish.


On the contrary. I speak the language of software architecture. This is the principle of dependency inversion. Low-level aspects should depend on high-level aspects.


More rubbish! High-level aspects (as I understand it, you're talking about business rules) cause low-level (as I understand it, you mean the database). So high-level modules depend on low-level modules in the same way that callers depend on callees. Everybody knows it!


In runtime, this is true. But at the time of compilation we need to invert the dependency. High-level source code should not mention low-level source code.


Well damn! You can't call something without mentioning it.


Sure you may. This is the essence of object orientation.


The essence of object orientation in modeling the real world, in the combination of data and functions in related objects. In organizing code into an intuitive architecture.


So they taught you?


Everybody knows it. Obviously, this is true.


No doubt. No doubt. And yet, using the principles of object orientation, you can actually call something without mentioning it.


OK How?


Do you know that in object-oriented design, objects send messages to each other?


Yes. Of course.


Do you know that the sender of the message does not know the type of recipient?


It depends on the language. in Java, the sender knows at least the base type of the recipient. In Ruby, the sender knows at a minimum that the recipient can process the message sent.


Yes. But neither in one nor the other case does the sender know the specific type of recipient.


Yeah. OK. Yes.


Consequently, the sender may be the cause of starting the function in the receiver, without mentioning the type of receiver.


Yeah. Right. I understand it. But the sender is still dependent on the recipient.


In runtime, yes. But not when compiling. The source code of the sender does not mention and does not depend on the source code of the recipient. The source code of the recipient depends on the source code of the sender.


Nooooo. The sender still depends on the class to which the message is sent.


Perhaps we need examples. I will write in java. First the sender's package:


package sender; public class Sender { private Receiver receiver; public Sender(Receiver r) { receiver = r; } public void doSomething() { receiver.receiveThis(); } public interface Receiver { void receiveThis(); } } 

Now the package is the recipient.


 package receiver; import sender.Sender; public class SpecificReceiver implements Sender.Receiver { public void receiveThis() { //do something interesting. } } 

Note that the recipient depends on the sender. Also note that the SpecificReceiver depends on Sender. And nothing in the sender knows about the recipient.


Yes, but this is cheating. You have inserted the receiver's interface into the sender class.


Now you begin to understand.


Understand what?


The principles of architecture, of course. Senders own the interfaces that recipients must implement.


If this means that you have to use nested classes, then ...


Nested classes are just one way to get things done. There are others.


OK, wait. And then the database? We started with this.


Let's take a look at another code. Here is the first business rule:


 package businessRules; import entities.Something; public class BusinessRule { private BusinessRuleGateway gateway; public BusinessRule(BusinessRuleGateway gateway) { this.gateway = gateway; } public void execute(String id) { gateway.startTransaction(); Something thing = gateway.getSomething(id); thing.makeChanges(); gateway.saveSomething(thing); gateway.endTransaction(); } } 

This business rule does nothing much.


This is just an example. You probably have many such classes that implement different rules.


OK, what is the Gateway there?


It provides all the data access methods that a business rule uses. Here is its implementation:


 package businessRules; import entities.Something; public interface BusinessRuleGateway { Something getSomething(String id); void startTransaction(); void saveSomething(Something thing); void endTransaction(); } 

Note that this is not a businessRules package.


Yeah, ok. What is the Something class?


It represents a simple business object. I put it in a package called entities.


 package entities; public class Something { public void makeChanges() { //... } } 

And finally, here is the implementation of BusinessRuleGateway. This class knows about the database itself:


 package database; import businessRules.BusinessRuleGateway; import entities.Something; public class MySqlBusinessRuleGateway implements BusinessRuleGateway { public Something getSomething(String id) { // use MySQL to get a thing. } public void startTransaction() { // start MySQL transaction } public void saveSomething(Something thing) { // save thing in MySQL } public void endTransaction() { // end MySql transaction } } 

Again, note that the business rules invoke the database at runtime, but at compile time this is done by the database package. It mentions and depends on thebusinessRules package.


Ok, ok, I think I understand. You simply use polymorphism to hide the database implementation from the business rules. But you still need an interface that provides business rules access to all database tools.


No, not at all. We are not trying to provide all the database tools to business rules. On the contrary, our business rules create interfaces only for what they need. The implementation of these interfaces may already invoke the appropriate tools.


Yeah, but if business rules need all these tools, then you have to put them all in the gateway interface.


Oh. I see that you still do not understand.


I do not understand what? It seems to me that everything is very clear.


Each business rule defines an interface only for the data access method it needs.


Stop. What?


This is called the interface separation principle. Each business rule class will use only part of the database engine. Therefore, each business rule provides an interface that gives it access only to these mechanisms.


But that means having to deal with a bunch of interfaces, and a bunch of small implementation classes to call other classes in the database.


Good. I see that now you begin to understand.


But this is a mess and a waste of time! Why do this?


To keep everything clean and save time.


Oh, everyone! It's just a bunch of code for the code.


On the contrary, these important architectural solutions will put off irrelevant decisions.


What do you mean?


Remember, you started with what you wanted to be a software architect? Did you want to make all the most important decisions?


Yes, that's what I want.


These solutions included a database, a web server and frameworks.


Yeah, and you said that these are not important decisions. You said that they do not play a special role.


Right. Do not play. The important decisions that the software architect makes allow you to NOT make decisions about the database, the web server, and the frameworks.


But you need to make these decisions at the beginning!


No no need. In fact, you need to make it possible to make these decisions much later in the development cycle - when there is more information.


Grief is an architect who chooses a database prematurely, and then realizes that a flat file structure would be enough.


Grief is an architect who chooses a web server prematurely, and then realizes that the team needed a simple socket-interface.


Grief is a team whose architect prematurely imposes a framework on it, and then realizes that the framework provides opportunities that they don’t need and adds restrictions that are impossible to live with.


Blessed is the team whose architects have provided a way to postpone all these decisions until the team has enough information to make them.


Blessed is the team whose architects have so well isolated them from demanding I / O devices and frameworks that the team is capable of creating fast and easy testing environments.


Blessed is the team whose architects are worried about really important things, and postpone not important ones.


Nonsense. I do not understand anything.


Well, maybe you will understand in ten years ... If you do not go to the managers.


')

Source: https://habr.com/ru/post/312366/


All Articles