{"id":1047,"date":"2023-10-22T00:42:45","date_gmt":"2023-10-21T22:42:45","guid":{"rendered":"https:\/\/easyrevitapi.com\/?p=1047"},"modified":"2024-04-29T10:29:47","modified_gmt":"2024-04-29T08:29:47","slug":"m-v-vm-pattern-for-revit-part-1","status":"publish","type":"post","link":"https:\/\/easyrevitapi.com\/index.php\/2023\/10\/22\/m-v-vm-pattern-for-revit-part-1\/","title":{"rendered":"M-V-VM Pattern for Revit, part 1"},"content":{"rendered":"\n<p class=\"justify-text\">Transitioning from Dynamo scripting to Autodesk\u00ae Revit Add-in development introduced me to a higher level of software complexity. It required me to consider various aspects, including database connections, user interface creation, authentication checks, and the organization of multiple C# and XAML files.<\/p>\n\n\n\n<p class=\"justify-text\">Architectural patterns are a good way of managing such complexity. They provide a frame to organise the different components of your add-in, and are valuable in guiding your development process.<\/p>\n\n\n\n<p class=\"justify-text\">In this first article of a three-part series, I will explain the main principles of the pattern I have been using, called the <strong>M<\/strong>odel<strong>-V<\/strong>iew<strong>-V<\/strong>iew<strong>M<\/strong>odel pattern. In the second part to come, I will present my implementation of this pattern for creating Revit Add-ins.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Software architecture<\/h4>\n\n\n\n<p class=\"justify-text\">In simple terms, software architecture<strong> <\/strong>is about defining the responsibility and organisation of the main parts of a system or application.<\/p>\n\n\n\n<p class=\"justify-text\"><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">Responsibility<\/mark><strong> <\/strong>means which types of actions and data a software&#8217;s part is concerned about, and which it isn&#8217;t. <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">Organization<\/mark> means how the software parts are linked and communicate with each others. It is about choosing which information is sent from a part to another, and how this transmission is made possible. It is also about managing the dependencies between these different parts and components.<\/p>\n\n\n\n<p class=\"justify-text\">A good software architecture in my opinion allows you to evolve and maintain software in the easiest and quickest way. For each update you want to make, you need to identify instantly where to intervene. Therefore, the organizing logic of the whole software system should be clear and coherent.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">M-V-VM pattern : the layers<br><br><\/h4>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized is-style-default\"><img loading=\"lazy\" decoding=\"async\" width=\"2048\" height=\"553\" src=\"https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Nouveau-projet-2023-10-21T194508.785-1.jpg\" alt=\"\" class=\"wp-image-1145\" style=\"aspect-ratio:3.7034358047016274;width:891px;height:auto\" srcset=\"https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Nouveau-projet-2023-10-21T194508.785-1.jpg 2048w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Nouveau-projet-2023-10-21T194508.785-1-300x81.jpg 300w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Nouveau-projet-2023-10-21T194508.785-1-1024x277.jpg 1024w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Nouveau-projet-2023-10-21T194508.785-1-768x207.jpg 768w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Nouveau-projet-2023-10-21T194508.785-1-1536x415.jpg 1536w\" sizes=\"auto, (max-width: 2048px) 100vw, 2048px\" \/><\/figure>\n\n\n\n<p class=\"justify-text\">The main purpose of the M-V-VM pattern is to define distinct layers for an application. On one hand, we have the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">Model<\/mark> representing (or <em>modeling<\/em>) the business data and logic. On the other hand, we have the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">View<\/mark> representing the graphical user interface.<\/p>\n\n\n\n<p class=\"justify-text\">This ensures that each part of our project&#8217;s codebase has a clear main responsibility, depending on the layer it belongs to. None of these two layers &#8216;know&#8217; about the other : the code of the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">Model<\/mark> doesn&#8217;t relate or intervene upon the code of the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">View<\/mark>, and vice-versa. <\/p>\n\n\n\n<p class=\"justify-text\">Such organisation refers to the <span style=\"text-decoration: underline;\">separation of concerns principle<\/span>. Besides making our application&#8217;s design and maintenance easier, it also reduces the risk of errors. Since the layers are decoupled, you won&#8217;t be breaking the UI code when updating the add-ins algorithms.<\/p>\n\n\n\n<p>Then comes the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">ViewModel<\/mark> : the intermediate layer between the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">Model<\/mark><strong> <\/strong>and the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">View<\/mark> :<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"471\" src=\"https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Manuscrit_2023-10-14_1936032-1024x471.jpg\" alt=\"\" class=\"wp-image-1074\" style=\"width:725px;height:auto\" srcset=\"https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Manuscrit_2023-10-14_1936032-1024x471.jpg 1024w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Manuscrit_2023-10-14_1936032-300x138.jpg 300w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Manuscrit_2023-10-14_1936032-768x354.jpg 768w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Manuscrit_2023-10-14_1936032-1536x707.jpg 1536w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Manuscrit_2023-10-14_1936032-2048x943.jpg 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"justify-text\">The <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">ViewModel<\/mark>&#8216;s responsibility is to <em>model <\/em>the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">View<\/mark><strong> <\/strong>by storing and managing all the collected or displayed data. This data can either be the input to be processed by the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">Model<\/mark>&#8216;s methods, or the output generated by these methods.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p class=\"justify-text\">The <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">ViewModel<\/mark><strong> <\/strong>serves as an interface for the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">View<\/mark><strong> <\/strong>to communicate with the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">Model<\/mark><strong> <\/strong>while maintaining the separation of concerns principle. This interface stores the results of the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">Model<\/mark>&#8216;s logic but does not contain the logic itself. However, it may include functionalities that filter or organize the information for display.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">M-V-VM pattern : the data flow<\/h4>\n\n\n\n<p>To help us better understand how the three layers of an M-V-VM application communicate, let&#8217;s consider a simple example. Let&#8217;s say we want to make an Add-in that returns the number of elements of a certain category contained in a Revit file.<\/p>\n\n\n\n<p class=\"justify-text\">The Add-in would work following these steps :<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li style=\"line-height:2\">The <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">View<\/mark><strong> <\/strong>displays the available categories within the Revit file<\/li>\n\n\n\n<li style=\"line-height:2\">The user selects one of these categories using the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">View<\/mark><\/li>\n\n\n\n<li style=\"line-height:2\">The <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">ViewModel<\/mark><strong> <\/strong>&#8220;listens&#8221; to the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">View<\/mark><strong> <\/strong>and records the user&#8217;s choice<\/li>\n\n\n\n<li style=\"line-height:2\">The user presses a button in the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">View<\/mark><strong> <\/strong>to count elements in the chosen category.<\/li>\n\n\n\n<li style=\"line-height:2\">The <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">ViewModel<\/mark><strong> <\/strong>records the user&#8217;s request and instructs the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">Model<\/mark><strong> <\/strong>to perform the required action.<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"471\" src=\"https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Manuscrit_2023-10-14_193603-1-1024x471.jpg\" alt=\"\" class=\"wp-image-1068\" srcset=\"https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Manuscrit_2023-10-14_193603-1-1024x471.jpg 1024w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Manuscrit_2023-10-14_193603-1-300x138.jpg 300w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Manuscrit_2023-10-14_193603-1-768x354.jpg 768w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Manuscrit_2023-10-14_193603-1-1536x707.jpg 1536w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Manuscrit_2023-10-14_193603-1-2048x943.jpg 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The next steps will be:<\/p>\n\n\n\n<ol class=\"wp-block-list\" start=\"6\">\n<li style=\"line-height:2\">The <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">Model <\/mark>accesses the Revit file, and filters all its elements of the chosen category <\/li>\n\n\n\n<li style=\"line-height:2\">It returns this processed data to the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">ViewModel<\/mark>, which records it <\/li>\n\n\n\n<li style=\"line-height:2\">The <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">ViewModel<\/mark><strong> <\/strong>then notifies the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">View<\/mark><strong> <\/strong>of its update<\/li>\n\n\n\n<li style=\"line-height:2\">The <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">View<\/mark><strong> <\/strong>&#8220;listens&#8221; to the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">ViewModel<\/mark><strong> <\/strong>and displays the elements requested by the user<br><\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"471\" src=\"https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Manuscrit_2023-10-14_193603-2-1024x471.jpg\" alt=\"\" class=\"wp-image-1069\" srcset=\"https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Manuscrit_2023-10-14_193603-2-1024x471.jpg 1024w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Manuscrit_2023-10-14_193603-2-300x138.jpg 300w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Manuscrit_2023-10-14_193603-2-768x354.jpg 768w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Manuscrit_2023-10-14_193603-2-1536x707.jpg 1536w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/10\/Manuscrit_2023-10-14_193603-2-2048x943.jpg 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>In summary,  the M-V-VM pattern enables bidirectional data flow, with information processed by the Model reaching the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">View<\/mark><strong> <\/strong>for user interaction and instructing the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">Model<\/mark><strong> <\/strong>in return. This allows the graphical user interface to remain interactive and responsive.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Conclusion<\/h4>\n\n\n\n<p>The M-V-VM pattern offers a clear frame for designing software. It drives you to define the responsibility of your application&#8217;s components, and gives you guidelines on how to link them. <\/p>\n\n\n\n<p>I think It&#8217;s an interesting pattern for managing a project&#8217;s complexity in the long run, addressing the evolution of both the algorithms and the graphical user interface.<\/p>\n\n\n\n<p>In the following article, I will share my implementation of the M-V-VM pattern for creating Autodesk Revit Add-ins using C# and WPF. Stay tuned \ud83d\ude09<\/p>\n\n\n\n<p><br><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Transitioning from Dynamo scripting to Autodesk\u00ae Revit Add-in development introduced me to a higher level of software complexity. It required me to consider various aspects, including database connections, user interface creation, authentication checks, and the organization of multiple C# and XAML files. Architectural patterns are a good way of managing such complexity. They provide a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1819,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[],"class_list":["post-1047","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-software-design"],"blocksy_meta":[],"_links":{"self":[{"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/posts\/1047","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/comments?post=1047"}],"version-history":[{"count":115,"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/posts\/1047\/revisions"}],"predecessor-version":[{"id":1820,"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/posts\/1047\/revisions\/1820"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/media\/1819"}],"wp:attachment":[{"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/media?parent=1047"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/categories?post=1047"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/tags?post=1047"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}