Уже некоторое время использую возможности прямого графа [DGML] и диаграммы слоев из VS2010. Использовали их во многих различных проектах с широким спектром архитектур, разным уровнем качества и множеством вопросов, чтобы ответить на них. И я узнал общий способ работы при использовании инструментов …
Это выглядит примерно так:
Уменьшить — Распознать — Увеличить — Анализировать — Уменьшить или Увеличить — Группировать — Уменьшить
и может быть сделано в другом порядке …
Некоторые примеры объяснят процесс анализа лучше.
Пример Хаоса. Сначала вопрос, вопрос о том, что анализировать, является отправной точкой и фактически ключевым фактором успеха вашего анализа. Самое смешное, что большинство проектных команд не знают, о чем спрашивать, они в основном кричат о помощи. То же самое относится и к такому проекту. Команда проекта нацеливалась на очень простую архитектуру с уровнем пользовательского интерфейса, бизнеса, данных и инфраструктуры. К сожалению, команде не удалось удержать контроль, и когда вы проводите анализ высокого уровня, « Zoom Out ». [Архитектура -> Создать график зависимостей -> По сборке или пространству имен, в большинстве случаев они одинаковы]
You get a direct graph, which probably makes everybody starts to cry or run a way “Recognize”… many connections, many dependencies which don’t belong there.
Although the funny thing is, when you us the default analyzers on this diagram, you won’t get any warnings….
“Analyze” There are no circular references, a trigger for tight coupling. There is one unreferenced node, for sure the outside pointing assembly [the UI] not strange. And, two assemblies are hubs, the data specific assemblies. This could be a trigger that these assemblies have too much responsibility.
Now at this stage of our analysis it’s interesting to take a look at the question… where are we looking for? it seems chaos, with the analyzers it looks like a kind of ok…. but it smells very bad.
The patterns and practices architecture guidance has a nice collection of:
It helps a lot when having these in our mind when executing an architectural analysis of a system… just to mention several:
- Separation of concerns.
- Single Responsibility principle
- Principle of Least Knowledge
- Don’t repeat yourself (DRY)
- Minimize upfront design
- Keep design patterns consistent within each layer.
- Do not duplicate functionality within an application.
- Prefer composition to inheritance
- Establish a coding style and naming convention for development
- Use abstraction to implement loose coupling between layers.
- Be explicit about how layers communicate with each other
- Do not mix different types of components in the same logical layer
- Keep crosscutting code abstracted from the application business logic as far as possible
- …
- …
Not all principles can be analyzed with Direct Graphs or Layer diagrams, but you can use some… the most important thing is that you know where you are looking for.
Now, lets zoom out… this direct graph we got gave us too much information to start our analysis with. It smells bad but what is wrong? sure, too much dependencies. Probably no good “Separation of concerns” and not been “explicit about how layers communicate with each other”… Start grouping assemblies [or namespace based on their parent namespace ] together.
Select the nodes which belong to each other and group them…
The Direct Graph we get now gives us much more information…
The UI talks with every single layer [assembly] in the system, but the thickness of the line tells us… the UI talks heavy to the business piece, sounds good… a lot to the framework and security assemblies, don’t know yet what their responsibilities are but the names are a kind of descriptive…
This is actually a funny part of the whole analysis thing, you really lean on the names used. A developer could call the UI layer data access, that would mess up my complete analysis.
Anyway, the problem is between the data access part and the business part. They are really tight coupled… the Web UI uses a bit of the data access, maybe some databound listbox “Recognize”. Not that important… Zooming in on this one “Zoom In” and selecting the dependency line between the data access and web component tells us…
.. that it is indeed a method… [only interested in methods]
… which does a data binding with a grid. [we will mark it needs some investigation]. Context menu item “Show Context” will jump to the code…
The tight coupling between data and business is a bigger challenge, when looking at the very very thick lines… they are really tight connected. Diving in these nodes “Zoom In” and looking at the different nodes, tells us… everyone from the data group points to “company.business.datasets”. that one isn’t a business component it contains real dataset [don’t know why its has “business” in the name..?]. Diving in the code shows something what we expect… generated datasets.
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30128.1
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
Moving the “company.business.datasets” to the data access group makes the dependency graph more clear… “Group”
The thing we still got in this system, is the connection between UI/ Web and the Data pieces… when zooming in on the Company.Web.Application you will see that about 50% of the types use the Business.DataSets… [context menu item on the DataSets node and select “all incoming”].
Probably all data binding stuff… now we have to make a decision. Refactoring the name of the Business.Datasets to DataAccess.DataSets would be useful. We can recommend that all UI binding should go through the business layer, than we need to start a big refactoring effort. We also could decide to binding of the UI with the datasets is fine [kind of Table Adapter Pattern]. It’s up to the architect. The thing dependencies which definitely have to remove are the ones with the dataacces assembly, there are just two calls. Create a dataset a bind it to those or create business entities.
So finally we come to some very specific recommendations how to improve this architecture… now it’s time to create a Layer Diagram. What I always do, is just drag and drop the different projects on the Layer diagram design surface and let it generate the dependencies…. again you get the scary one ?
Start group components together in layers and draw the dependencies as decided with the project lead and architect… till you get to the result you wanted, for your architecture….
And now, we can run the validation… the errors which show up are the code pieces you need to fix. When your ready fixing those, maybe you want to clean/ refractor the architecture even more, maybe remove the datasets and talk only through the businesslayer… change the dependency rules and validate again… in this way the errors which show up are more in control and you can do the refactoring step by step.
It was a fun journey ?
Zoom Out – Recognize — Zoom In – Analyze — Zoom Out or Zoom In – Group – Zoom Out and finally VALIDATE