From 9fe1d9882d85970442fa706d5a412b0e64984aea Mon Sep 17 00:00:00 2001 From: MPostol Date: Thu, 20 Jun 2024 22:29:18 +0200 Subject: [PATCH] ExDM Add documentation to the selected parts of the code #369 - working on the MVVM in the README.MVVM.md document - finished first attempt --- ExDataManagement/GraphicalData/README.MVVM.md | 107 +++++------------- 1 file changed, 29 insertions(+), 78 deletions(-) diff --git a/ExDataManagement/GraphicalData/README.MVVM.md b/ExDataManagement/GraphicalData/README.MVVM.md index 9216612..fc88ea6 100644 --- a/ExDataManagement/GraphicalData/README.MVVM.md +++ b/ExDataManagement/GraphicalData/README.MVVM.md @@ -38,12 +38,10 @@ - [6.1. Introduction](#61-introduction) - [6.2. Layer Implementation using project concept](#62-layer-implementation-using-project-concept) - [6.3. MVVM as Sub-layers of the Presentation Layer](#63-mvvm-as-sub-layers-of-the-presentation-layer) - - [6.4. Diagram View](#64-diagram-view) - - [6.5. Porządkowanie diagramu](#65-porządkowanie-diagramu) - - [6.6. Jak Zaimplementować](#66-jak-zaimplementować) - - [6.7. Implementacja warstw ogólnej architektury programu](#67-implementacja-warstw-ogólnej-architektury-programu) - - [6.8. Powody Wprowadzenia Warstw](#68-powody-wprowadzenia-warstw) - - [6.9. Wstrzykiwanie zależności View](#69-wstrzykiwanie-zależności-view) + - [6.4. Code Map Diagram](#64-code-map-diagram) + - [6.5. Implementacja warstw ogólnej architektury programu](#65-implementacja-warstw-ogólnej-architektury-programu) + - [6.6. Layered architecture Benefits](#66-layered-architecture-benefits) + - [6.7. View - Inversion of Control](#67-view---inversion-of-control) ## 1. Introduction @@ -191,99 +189,52 @@ Before examining the gathered examples, first I must remind you that the algorit We already proved that theoretically a layered program design pattern is very beneficial. Simplifying, by design, layered program design pattern applies to the program as one whole - keeping in mind - that the program is just a text. A program is just a text compliant with a selected programming language. Hence the pattern including the layers and layers relationship must be expressed using terminology defined by the language itself. Further discussion may depend on the selection of a concrete programming language. Therefore, according to the rules the further discussion is conducted using CSharp as the programming language and Visual Studio as the development environment. -Languages offering object-oriented programming usually use the custom types definitions as building blocks that take responsibility to implement the algorithm/data in concern. It is also the case for the CSharp programming language. Additionally the layered architecture is also abstract term and therefore must be implemented somehow. To implement the layers I propose sets of custom-type definitions. Answering the question of what is a layer, the answer is it is a set of custom types. In maths, sets are a group of well-defined entities called members of the set. In the proposed case the well-defined entity is a custom type - a language construct. The set notion is derived from the mathematical theory and is well known from the background school education, hence we may skip deep diving into this theory. The only important thing is how to recognize the membership. There must be a boundary that we can use to distinguish if a type belongs to the selected set or not. To make the layer unambiguous it must be assumed that any type belongs only to one set, to one layer. This way we can convert the discussion about mathematical sets to an examination of types grouping. Now we must answer a question about how to recognize the membership of a type. In other words the fact of being a member of a selected group. +The layered architecture is also abstract term and therefore must be implemented somehow. High-level programming languages are designed to be more intuitive and user-friendly for human programmers. They usually use the custom types definitions as building blocks that take responsibility to implement the algorithm/data in concern. To implement the layers I propose **sets of custom-type definitions**. In maths, the set is a group of well-defined entities called members. The set notion is well known from the background school education, hence we may skip deep diving into this theory. In the proposed approach the well-defined entity is a custom type - a language construct. The only important thing is how to recognize the membership. There must be a boundary that we can use to distinguish if a type belongs to the selected set or not. To make the layer unambiguous it must be assumed that any type belongs only to one set, to one layer. This way we can convert the discussion about mathematical sets to an examination of types grouping. Now we must answer a question about how to recognize the membership of a type. In other words the fact of being a member of a selected group. The namespace construct could be a relief to help make up a boundary of the set and finally of a layer. Namespaces are used to organize and provide a level of separation of program parts and to avoid name collisions. The namespace unique name could be used as a prefix of an identifier of the definition to make the full name unique in the program scope. On the other hand, the namespace can also be considered a container or an organization unit of definitions. This concept perfectly fits the concept of grouping or more formally enforcing set membership of types. -This concept is illustrated in the figure below where we have three main layers created using the proposed method. It was generated from the text gathered in the `Graphical Data` folder. This image has been created using a code analytic tool embedded in the development environment. After removing not important parts, thanks to this image we can distinguish three layers, called View, ViewModel, and Model. It is also worth notifying that internally inside the layer circular dependencies are perfectly OK. Let me recall that only between layers we must have unidirectional top-down dependencies. As a side effect of using the embedded tool to analyze the architecture of the program text, there are different kinds of arrows. We may safely neglect this. This tool is not a subject of our examination. +This concept is illustrated in the figure below. In this diagram where we can recognize three main layers created using the proposed method. It was generated from the text gathered in the `Graphical Data` folder. This image has been created using a code analytic tool embedded in the development environment. After removing not important parts, thanks to this image we can distinguish three layers, called View, ViewModel, and Model. It is also worth notifying that internally inside the layer circular dependencies are perfectly OK. Let me recall that only between layers we must have unidirectional top-down dependencies. As a side effect of using the embedded tool to analyze the architecture of the program text, there are different kinds of arrows. We may safely neglect this. This tool is not a subject of our examination. ![MVVM Layered Architecture](.Media/MVVMLayeredArchitecture.png) -Minimizing the number of projects in a solution reduces maintenance costs and reduces dependency hell, so if portability is not a goal it may not be worth forcing separate projects. However, here we are dealing with a scenario where portability is critical, so separating projects is justified. The purpose of implementing layers using projects may be to minimize the program area dependent on technology by limiting the dependency on one project only. Let me give you an example. There is no doubt. A graphical user interface should be implemented differently for desktop devices equipped with a high-resolution monitor and for smartphone devices. So let's try to put forward the thesis that layers can be implemented using projects. +The purpose of implementing layers using independent projects may be to minimize the program area dependent on technology. On the other hand, minimizing the number of projects in a solution reduces maintenance costs and dependency hell. Hence, if there are no special reasons it may not be worth forcing separate projects. However, here we are dealing with a scenario where portability is critical, so separating projects is justified. Let me give you an example. A graphical user interface should be implemented differently for desktop devices with high-resolution monitors and smartphone devices. So let's try to put forward the thesis that layers can be implemented using projects. -From the point of view of the development environment, a project is just an organizational unit within the solution. Solution and project are concepts related to the tool like Visual Studio, and not to the program text consistent with the selected programming language. This would indicate that using projects to implement layers is not a good idea because it has no direct connection with the programming language. However, we must consider an important feature of a solution project - the project is also a compilation unit. Therefore, its content must be consistent and compliant with a programming language. It can be treated as the boundary of a set of type definitions. Unidirectional and hierarchical top-down relationships can be implemented using the References/Dependencies project branches, as shown in the figure below. Additionally, in the case of projects compared to namespaces, type definitions visibility control can be employed, which should further facilitate the implementation of a layer as a set of type definitions and hierarchical unidirectional relationships between layers. +From the development environment point of view, a project is just an organizational unit within the solution. Solution and project are concepts related to the tool like Visual Studio, and not to the program text consistent with the selected programming language. This would indicate that using projects to implement layers is not a good idea. It looks like this concept has no direct connection with the programming language. However, we must consider an important project feature within a solution- the project is also a compilation unit. Therefore, its content must be consistent and compliant with a programming language. Hence, despite everything, it can be treated as the boundary of a set of type definitions. Unidirectional and hierarchical top-down relationships can be implemented using the References/Dependencies branches. Additionally, in the case of projects compared to namespaces, type definitions visibility control can be employed, which should further facilitate the implementation of a layer as a set of type definitions and hierarchical unidirectional relationships between layers. The same as the previous code snippet is shown in the figure below but now employing projects as implementation of the MVVM layers. ![MVVM Layered Architecture Using Projects](.Media/MVVMLayeredArchitectureProjectBased.png) -### 6.4. Diagram View +### 6.4. Code Map Diagram -### 6.5. Porządkowanie diagramu +Let's start the analysis of the implementation of the MVVM pattern and the implementation of the Model, View, and ViewModel layers by generating a diagram showing various relationships occurring in the text of the example program. We start with a project containing text describing the interface graphics, i.e. the View layer. Let me remind you that it was implemented in a separate project grouping all references to WPF technology, i.e. to a certain group of types whose definition is embedded in precisely defined external realities, in this case of the operating system. In the presented diagram we have three components: The solution folder, the project, and, after expanding the project, its namespaces. Let's add to the diagram projects containing the rest of the program. After extending it shows the content. -### 6.6. Jak Zaimplementować +Let's examine in detail the implementation of MVVM layers using these examples. The layer is an abstract notion, hence we must use some language construct that will be used for this purpose. In other words, the program is text, so the layer must be a separate fragment of this text. -### 6.7. Implementacja warstw ogólnej architektury programu +A namespace is a linguistic construct and contains a group of type definitions, so it seems like a good candidate for implementing layers. It's also easy to isolate text within a namespace of your choice. So, using filters, let's remove all organizational elements related to the tool. In this case, it is the folder and projects. After tidying up the diagram, we see that the layers have been implemented as namespaces. Within the namespaces creating the layers, there may be additional namespaces containing definitions of auxiliary types within the MVVMLight namespace, I have defined two auxiliary classes that facilitate the implementation and control of the correct use of this pattern and provide the functionality needed for the ViewModel layer. It contains an implementation of two interfaces, namely INotifyPropertyChange and ICommand. -### 6.8. Powody Wprowadzenia Warstw +Using this example, let's define a few simplified rules that will make it easier to implement the MVVM pattern. -### 6.9. Wstrzykiwanie zależności View +1. Only definitions that refer to types defined in the PresentationFramework should be gathered in the View layer. Additionally, these definitions can only refer to types defined in the ViewModel space. By design, we only include text written in XAML and empty definitions in the code-behind part in the View layer. +2. In the ViewModel layer, we define all types whose objects are bound to the properties of the controls. Placing definitions of auxiliary types here to meet the requirements for this layer is optional. Due to the universal nature of these implementations, we often use external libraries. +3. To put it simply, the Model layer is everything else. The Model layer encapsulates the functionality and data-related operations relevant to implementing a graphical user interface and ensuring a clean separation from the UI rest of the program. It allows developers to work on business logic independently of the view, making the application easier to test, maintain, and evolve. - \ No newline at end of file +After taking a closer look at the example implementation of the View layer in the MainWindow class, we notice that the empty code-behind rule is not fully held. The exception we see here is solely related to ensuring layer decoupling - i.e. ensuring hierarchical references. I leave the detailed analysis as homework.