public void Test_AddNearestNeighbours_AddsNearestNeighbours_WhenThereAreSomeNearestNeighbours()
        {
            SoftwareSystem softwareSystemA = model.AddSoftwareSystem("System A", "Description");
            SoftwareSystem softwareSystemB = model.AddSoftwareSystem("System B", "Description");
            Person         userA           = model.AddPerson("User A", "Description");
            Person         userB           = model.AddPerson("User B", "Description");

            // userA -> systemA -> system -> systemB -> userB
            userA.Uses(softwareSystemA, "");
            softwareSystemA.Uses(softwareSystem, "");
            softwareSystem.Uses(softwareSystemB, "");
            softwareSystemB.Delivers(userB, "");

            // userA -> systemA -> web application -> systemB -> userB
            // web application -> database
            Container webApplication = softwareSystem.AddContainer("Web Application", "", "");
            Container database       = softwareSystem.AddContainer("Database", "", "");

            softwareSystemA.Uses(webApplication, "");
            webApplication.Uses(softwareSystemB, "");
            webApplication.Uses(database, "");

            // userA -> systemA -> controller -> service -> repository -> database
            Component controller = webApplication.AddComponent("Controller", "");
            Component service    = webApplication.AddComponent("Service", "");
            Component repository = webApplication.AddComponent("Repository", "");

            softwareSystemA.Uses(controller, "");
            controller.Uses(service, "");
            service.Uses(repository, "");
            repository.Uses(database, "");

            // userA -> systemA -> controller -> service -> systemB -> userB
            service.Uses(softwareSystemB, "");

            view.AddNearestNeighbours(softwareSystem);

            Assert.AreEqual(3, view.Elements.Count);
            Assert.IsTrue(view.Elements.Contains(new ElementView(softwareSystemA)));
            Assert.IsTrue(view.Elements.Contains(new ElementView(softwareSystem)));
            Assert.IsTrue(view.Elements.Contains(new ElementView(softwareSystemB)));

            view = new SystemContextView(softwareSystem, "context", "Description");
            view.AddNearestNeighbours(softwareSystemA);

            Assert.AreEqual(3, view.Elements.Count);
            Assert.IsTrue(view.Elements.Contains(new ElementView(userA)));
            Assert.IsTrue(view.Elements.Contains(new ElementView(softwareSystemA)));
            Assert.IsTrue(view.Elements.Contains(new ElementView(softwareSystem)));
        }
Example #2
0
        static void Main()
        {
            Workspace workspace = new Workspace("Widgets Limited", "Sells widgets to customers online.");
            Model     model     = workspace.Model;
            ViewSet   views     = workspace.Views;
            Styles    styles    = views.Configuration.Styles;

            model.Enterprise = new Enterprise("Widgets Limited");

            Person         customer            = model.AddPerson(Location.External, "Customer", "A customer of Widgets Limited.");
            Person         customerServiceUser = model.AddPerson(Location.Internal, "Customer Service Agent", "Deals with customer enquiries.");
            SoftwareSystem ecommerceSystem     = model.AddSoftwareSystem(Location.Internal, "E-commerce System", "Allows customers to buy widgets online via the widgets.com website.");
            SoftwareSystem fulfilmentSystem    = model.AddSoftwareSystem(Location.Internal, "Fulfilment System", "Responsible for processing and shipping of customer orders.");
            SoftwareSystem taxamo = model.AddSoftwareSystem(Location.External, "Taxamo", "Calculates local tax (for EU B2B customers) and acts as a front-end for Braintree Payments.");

            taxamo.Url = "https://www.taxamo.com";
            SoftwareSystem braintreePayments = model.AddSoftwareSystem(Location.External, "Braintree Payments", "Processes credit card payments on behalf of Widgets Limited.");

            braintreePayments.Url = "https://www.braintreepayments.com";
            SoftwareSystem jerseyPost = model.AddSoftwareSystem(Location.External, "Jersey Post", "Calculates worldwide shipping costs for packages.");

            model.People.Where(p => p.Location == Location.External).ToList().ForEach(p => p.AddTags(ExternalTag));
            model.People.Where(p => p.Location == Location.Internal).ToList().ForEach(p => p.AddTags(InternalTag));

            model.SoftwareSystems.Where(ss => ss.Location == Location.External).ToList().ForEach(ss => ss.AddTags(ExternalTag));
            model.SoftwareSystems.Where(ss => ss.Location == Location.Internal).ToList().ForEach(ss => ss.AddTags(InternalTag));

            customer.InteractsWith(customerServiceUser, "Asks questions to", "Telephone");
            customerServiceUser.Uses(ecommerceSystem, "Looks up order information using");
            customer.Uses(ecommerceSystem, "Places orders for widgets using");
            ecommerceSystem.Uses(fulfilmentSystem, "Sends order information to");
            fulfilmentSystem.Uses(jerseyPost, "Gets shipping charges from");
            ecommerceSystem.Uses(taxamo, "Delegates credit card processing to");
            taxamo.Uses(braintreePayments, "Uses for credit card processing");

            EnterpriseContextView enterpriseContextView = views.CreateEnterpriseContextView("EnterpriseContext", "The enterprise context for Widgets Limited.");

            enterpriseContextView.AddAllElements();

            SystemContextView ecommerceSystemContext = views.CreateSystemContextView(ecommerceSystem, "EcommerceSystemContext", "The system context diagram for the Widgets Limited e-commerce system.");

            ecommerceSystemContext.AddNearestNeighbours(ecommerceSystem);
            ecommerceSystemContext.Remove(customer.GetEfferentRelationshipWith(customerServiceUser));

            SystemContextView fulfilmentSystemContext = views.CreateSystemContextView(fulfilmentSystem, "FulfilmentSystemContext", "The system context diagram for the Widgets Limited fulfilment system.");

            fulfilmentSystemContext.AddNearestNeighbours(fulfilmentSystem);

            DynamicView dynamicView = views.CreateDynamicView("CustomerSupportCall", "A high-level overview of the customer support call process.");

            dynamicView.Add(customer, customerServiceUser);
            dynamicView.Add(customerServiceUser, ecommerceSystem);

            StructurizrDocumentationTemplate template = new StructurizrDocumentationTemplate(workspace);

            template.AddSection("Enterprise Context", 1, Format.Markdown, "Here is some information about the Widgets Limited enterprise context... ![](embed:EnterpriseContext)");
            template.AddContextSection(ecommerceSystem, Format.Markdown, "This is the context section for the E-commerce System... ![](embed:EcommerceSystemContext)");
            template.AddContextSection(fulfilmentSystem, Format.Markdown, "This is the context section for the Fulfilment System... ![](embed:FulfilmentSystemContext)");

            styles.Add(new ElementStyle(Tags.SoftwareSystem)
            {
                Shape = Shape.RoundedBox
            });
            styles.Add(new ElementStyle(Tags.Person)
            {
                Shape = Shape.Person
            });

            styles.Add(new ElementStyle(Tags.Element)
            {
                Color = "#ffffff"
            });
            styles.Add(new ElementStyle(ExternalTag)
            {
                Background = "#EC5381", Border = Border.Dashed
            });
            styles.Add(new ElementStyle(InternalTag)
            {
                Background = "#B60037"
            });

            StructurizrClient structurizrClient = new StructurizrClient(ApiKey, ApiSecret);

            structurizrClient.PutWorkspace(WorkspaceId, workspace);
        }
        public static Workspace Create()
        {
            Workspace workspace = new Workspace("Big Bank plc", "This is an example workspace to illustrate the key features of Structurizr, based around a fictional online banking system.");
            Model     model     = workspace.Model;
            ViewSet   views     = workspace.Views;

            model.Enterprise = new Enterprise("Big Bank plc");

            // people and software systems
            Person customer = model.AddPerson(Location.External, "Personal Banking Customer", "A customer of the bank, with personal bank accounts.");

            SoftwareSystem internetBankingSystem = model.AddSoftwareSystem(Location.Internal, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.");

            customer.Uses(internetBankingSystem, "Uses");

            SoftwareSystem mainframeBankingSystem = model.AddSoftwareSystem(Location.Internal, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.");

            mainframeBankingSystem.AddTags(ExistingSystemTag);
            internetBankingSystem.Uses(mainframeBankingSystem, "Uses");

            SoftwareSystem emailSystem = model.AddSoftwareSystem(Location.Internal, "E-mail System", "The internal Microsoft Exchange e-mail system.");

            internetBankingSystem.Uses(emailSystem, "Sends e-mail using");
            emailSystem.AddTags(ExistingSystemTag);
            emailSystem.Delivers(customer, "Sends e-mails to");

            SoftwareSystem atm = model.AddSoftwareSystem(Location.Internal, "ATM", "Allows customers to withdraw cash.");

            atm.AddTags(ExistingSystemTag);
            atm.Uses(mainframeBankingSystem, "Uses");
            customer.Uses(atm, "Withdraws cash using");

            Person customerServiceStaff = model.AddPerson(Location.Internal, "Customer Service Staff", "Customer service staff within the bank.");

            customerServiceStaff.AddTags(BankStaffTag);
            customerServiceStaff.Uses(mainframeBankingSystem, "Uses");
            customer.InteractsWith(customerServiceStaff, "Asks questions to", "Telephone");

            Person backOfficeStaff = model.AddPerson(Location.Internal, "Back Office Staff", "Administration and support staff within the bank.");

            backOfficeStaff.AddTags(BankStaffTag);
            backOfficeStaff.Uses(mainframeBankingSystem, "Uses");

            // containers
            Container singlePageApplication = internetBankingSystem.AddContainer("Single-Page Application", "Provides all of the Internet banking functionality to customers via their web browser.", "JavaScript and Angular");

            singlePageApplication.AddTags(WebBrowserTag);
            Container mobileApp = internetBankingSystem.AddContainer("Mobile App", "Provides a limited subset of the Internet banking functionality to customers via their mobile device.", "Xamarin");

            mobileApp.AddTags(MobileAppTag);
            Container webApplication = internetBankingSystem.AddContainer("Web Application", "Delivers the static content and the Internet banking single page application.", "Java and Spring MVC");
            Container apiApplication = internetBankingSystem.AddContainer("API Application", "Provides Internet banking functionality via a JSON/HTTPS API.", "Java and Spring MVC");
            Container database       = internetBankingSystem.AddContainer("Database", "Stores user registration information, hashed authentication credentials, access logs, etc.", "Relational Database Schema");

            database.AddTags(DatabaseTag);

            customer.Uses(webApplication, "Uses", "HTTPS");
            customer.Uses(singlePageApplication, "Uses", "");
            customer.Uses(mobileApp, "Uses", "");
            webApplication.Uses(singlePageApplication, "Delivers to the customer's web browser", "");
            apiApplication.Uses(database, "Reads from and writes to", "JDBC");
            apiApplication.Uses(mainframeBankingSystem, "Uses", "XML/HTTPS");
            apiApplication.Uses(emailSystem, "Sends e-mail using", "SMTP");

            // components
            // - for a real-world software system, you would probably want to extract the components using
            // - static analysis/reflection rather than manually specifying them all
            Component signinController             = apiApplication.AddComponent("Sign In Controller", "Allows users to sign in to the Internet Banking System.", "Spring MVC Rest Controller");
            Component accountsSummaryController    = apiApplication.AddComponent("Accounts Summary Controller", "Provides customers with a summary of their bank accounts.", "Spring MVC Rest Controller");
            Component resetPasswordController      = apiApplication.AddComponent("Reset Password Controller", "Allows users to reset their passwords with a single use URL.", "Spring MVC Rest Controller");
            Component securityComponent            = apiApplication.AddComponent("Security Component", "Provides functionality related to signing in, changing passwords, etc.", "Spring Bean");
            Component mainframeBankingSystemFacade = apiApplication.AddComponent("Mainframe Banking System Facade", "A facade onto the mainframe banking system.", "Spring Bean");
            Component emailComponent = apiApplication.AddComponent("E-mail Component", "Sends e-mails to users.", "Spring Bean");

            apiApplication.Components.Where(c => "Spring MVC Rest Controller".Equals(c.Technology)).ToList().ForEach(c => singlePageApplication.Uses(c, "Makes API calls to", "JSON/HTTPS"));
            apiApplication.Components.Where(c => "Spring MVC Rest Controller".Equals(c.Technology)).ToList().ForEach(c => mobileApp.Uses(c, "Makes API calls to", "JSON/HTTPS"));
            signinController.Uses(securityComponent, "Uses");
            accountsSummaryController.Uses(mainframeBankingSystemFacade, "Uses");
            resetPasswordController.Uses(securityComponent, "Uses");
            resetPasswordController.Uses(emailComponent, "Uses");
            securityComponent.Uses(database, "Reads from and writes to", "JDBC");
            mainframeBankingSystemFacade.Uses(mainframeBankingSystem, "Uses", "XML/HTTPS");
            emailComponent.Uses(emailSystem, "Sends e-mail using");

            model.AddImplicitRelationships();

            // deployment nodes and container instances
            DeploymentNode developerLaptop = model.AddDeploymentNode("Development", "Developer Laptop", "A developer laptop.", "Microsoft Windows 10 or Apple macOS");
            DeploymentNode apacheTomcat    = developerLaptop.AddDeploymentNode("Docker Container - Web Server", "A Docker container.", "Docker")
                                             .AddDeploymentNode("Apache Tomcat", "An open source Java EE web server.", "Apache Tomcat 8.x", 1, DictionaryUtils.Create("Xmx=512M", "Xms=1024M", "Java Version=8"));

            apacheTomcat.Add(webApplication);
            apacheTomcat.Add(apiApplication);

            developerLaptop.AddDeploymentNode("Docker Container - Database Server", "A Docker container.", "Docker")
            .AddDeploymentNode("Database Server", "A development database.", "Oracle 12c")
            .Add(database);

            developerLaptop.AddDeploymentNode("Web Browser", "", "Chrome, Firefox, Safari, or Edge").Add(singlePageApplication);

            DeploymentNode customerMobileDevice = model.AddDeploymentNode("Live", "Customer's mobile device", "", "Apple iOS or Android");

            customerMobileDevice.Add(mobileApp);

            DeploymentNode customerComputer = model.AddDeploymentNode("Live", "Customer's computer", "", "Microsoft Windows or Apple macOS");

            customerComputer.AddDeploymentNode("Web Browser", "", "Chrome, Firefox, Safari, or Edge").Add(singlePageApplication);

            DeploymentNode bigBankDataCenter = model.AddDeploymentNode("Live", "Big Bank plc", "", "Big Bank plc data center");

            DeploymentNode liveWebServer = bigBankDataCenter.AddDeploymentNode("bigbank-web***", "A web server residing in the web server farm, accessed via F5 BIG-IP LTMs.", "Ubuntu 16.04 LTS", 4, DictionaryUtils.Create("Location=London and Reading"));

            liveWebServer.AddDeploymentNode("Apache Tomcat", "An open source Java EE web server.", "Apache Tomcat 8.x", 1, DictionaryUtils.Create("Xmx=512M", "Xms=1024M", "Java Version=8"))
            .Add(webApplication);

            DeploymentNode liveApiServer = bigBankDataCenter.AddDeploymentNode("bigbank-api***", "A web server residing in the web server farm, accessed via F5 BIG-IP LTMs.", "Ubuntu 16.04 LTS", 8, DictionaryUtils.Create("Location=London and Reading"));

            liveApiServer.AddDeploymentNode("Apache Tomcat", "An open source Java EE web server.", "Apache Tomcat 8.x", 1, DictionaryUtils.Create("Xmx=512M", "Xms=1024M", "Java Version=8"))
            .Add(apiApplication);

            DeploymentNode primaryDatabaseServer = bigBankDataCenter.AddDeploymentNode("bigbank-db01", "The primary database server.", "Ubuntu 16.04 LTS", 1, DictionaryUtils.Create("Location=London"))
                                                   .AddDeploymentNode("Oracle - Primary", "The primary, live database server.", "Oracle 12c");

            primaryDatabaseServer.Add(database);

            DeploymentNode bigBankdb02 = bigBankDataCenter.AddDeploymentNode("bigbank-db02", "The secondary database server.", "Ubuntu 16.04 LTS", 1, DictionaryUtils.Create("Location=Reading"));

            bigBankdb02.AddTags(FailoverTag);
            DeploymentNode secondaryDatabaseServer = bigBankdb02.AddDeploymentNode("Oracle - Secondary", "A secondary, standby database server, used for failover purposes only.", "Oracle 12c");

            secondaryDatabaseServer.AddTags(FailoverTag);
            ContainerInstance secondaryDatabase = secondaryDatabaseServer.Add(database);

            model.Relationships.Where(r => r.Destination.Equals(secondaryDatabase)).ToList().ForEach(r => r.AddTags(FailoverTag));
            Relationship dataReplicationRelationship = primaryDatabaseServer.Uses(secondaryDatabaseServer, "Replicates data to", "");

            secondaryDatabase.AddTags(FailoverTag);

            // views/diagrams
            SystemLandscapeView systemLandscapeView = views.CreateSystemLandscapeView("SystemLandscape", "The system landscape diagram for Big Bank plc.");

            systemLandscapeView.AddAllElements();
            systemLandscapeView.PaperSize = PaperSize.A5_Landscape;

            SystemContextView systemContextView = views.CreateSystemContextView(internetBankingSystem, "SystemContext", "The system context diagram for the Internet Banking System.");

            systemContextView.EnterpriseBoundaryVisible = false;
            systemContextView.AddNearestNeighbours(internetBankingSystem);
            systemContextView.PaperSize = PaperSize.A5_Landscape;

            ContainerView containerView = views.CreateContainerView(internetBankingSystem, "Containers", "The container diagram for the Internet Banking System.");

            containerView.Add(customer);
            containerView.AddAllContainers();
            containerView.Add(mainframeBankingSystem);
            containerView.Add(emailSystem);
            containerView.PaperSize = PaperSize.A5_Landscape;

            ComponentView componentView = views.CreateComponentView(apiApplication, "Components", "The component diagram for the API Application.");

            componentView.Add(mobileApp);
            componentView.Add(singlePageApplication);
            componentView.Add(database);
            componentView.AddAllComponents();
            componentView.Add(mainframeBankingSystem);
            componentView.Add(emailSystem);
            componentView.PaperSize = PaperSize.A5_Landscape;

            systemLandscapeView.AddAnimation(internetBankingSystem, customer, mainframeBankingSystem, emailSystem);
            systemLandscapeView.AddAnimation(atm);
            systemLandscapeView.AddAnimation(customerServiceStaff, backOfficeStaff);

            systemContextView.AddAnimation(internetBankingSystem);
            systemContextView.AddAnimation(customer);
            systemContextView.AddAnimation(mainframeBankingSystem);
            systemContextView.AddAnimation(emailSystem);

            containerView.AddAnimation(customer, mainframeBankingSystem, emailSystem);
            containerView.AddAnimation(webApplication);
            containerView.AddAnimation(singlePageApplication);
            containerView.AddAnimation(mobileApp);
            containerView.AddAnimation(apiApplication);
            containerView.AddAnimation(database);

            componentView.AddAnimation(singlePageApplication, mobileApp);
            componentView.AddAnimation(signinController, securityComponent, database);
            componentView.AddAnimation(accountsSummaryController, mainframeBankingSystemFacade, mainframeBankingSystem);
            componentView.AddAnimation(resetPasswordController, emailComponent, database);

            // dynamic diagrams and deployment diagrams are not available with the Free Plan
            DynamicView dynamicView = views.CreateDynamicView(apiApplication, "SignIn", "Summarises how the sign in feature works in the single-page application.");

            dynamicView.Add(singlePageApplication, "Submits credentials to", signinController);
            dynamicView.Add(signinController, "Calls isAuthenticated() on", securityComponent);
            dynamicView.Add(securityComponent, "select * from users where username = ?", database);
            dynamicView.PaperSize = PaperSize.A5_Landscape;

            DeploymentView developmentDeploymentView = views.CreateDeploymentView(internetBankingSystem, "DevelopmentDeployment", "An example development deployment scenario for the Internet Banking System.");

            developmentDeploymentView.Environment = "Development";
            developmentDeploymentView.Add(developerLaptop);
            developmentDeploymentView.PaperSize = PaperSize.A5_Landscape;

            DeploymentView liveDeploymentView = views.CreateDeploymentView(internetBankingSystem, "LiveDeployment", "An example live deployment scenario for the Internet Banking System.");

            liveDeploymentView.Environment = "Live";
            liveDeploymentView.Add(bigBankDataCenter);
            liveDeploymentView.Add(customerMobileDevice);
            liveDeploymentView.Add(customerComputer);
            liveDeploymentView.Add(dataReplicationRelationship);
            liveDeploymentView.PaperSize = PaperSize.A5_Landscape;

            // colours, shapes and other diagram styling
            Styles styles = views.Configuration.Styles;

            styles.Add(new ElementStyle(Tags.SoftwareSystem)
            {
                Background = "#1168bd", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(Tags.Container)
            {
                Background = "#438dd5", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(Tags.Component)
            {
                Background = "#85bbf0", Color = "#000000"
            });
            styles.Add(new ElementStyle(Tags.Person)
            {
                Background = "#08427b", Color = "#ffffff", Shape = Shape.Person, FontSize = 22
            });
            styles.Add(new ElementStyle(ExistingSystemTag)
            {
                Background = "#999999", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(BankStaffTag)
            {
                Background = "#999999", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(WebBrowserTag)
            {
                Shape = Shape.WebBrowser
            });
            styles.Add(new ElementStyle(MobileAppTag)
            {
                Shape = Shape.MobileDeviceLandscape
            });
            styles.Add(new ElementStyle(DatabaseTag)
            {
                Shape = Shape.Cylinder
            });
            styles.Add(new ElementStyle(FailoverTag)
            {
                Opacity = 25
            });
            styles.Add(new RelationshipStyle(FailoverTag)
            {
                Opacity = 25, Position = 70
            });

            // documentation
            // - usually the documentation would be included from separate Markdown/AsciiDoc files, but this is just an example
            StructurizrDocumentationTemplate template = new StructurizrDocumentationTemplate(workspace);

            template.AddContextSection(internetBankingSystem, Format.Markdown,
                                       "Here is some context about the Internet Banking System...\n" +
                                       "![](embed:SystemLandscape)\n" +
                                       "![](embed:SystemContext)\n" +
                                       "### Internet Banking System\n...\n" +
                                       "### Mainframe Banking System\n...\n");
            template.AddContainersSection(internetBankingSystem, Format.Markdown,
                                          "Here is some information about the containers within the Internet Banking System...\n" +
                                          "![](embed:Containers)\n" +
                                          "### Web Application\n...\n" +
                                          "### Database\n...\n");
            template.AddComponentsSection(webApplication, Format.Markdown,
                                          "Here is some information about the API Application...\n" +
                                          "![](embed:Components)\n" +
                                          "### Sign in process\n" +
                                          "Here is some information about the Sign In Controller, including how the sign in process works...\n" +
                                          "![](embed:SignIn)");
            template.AddDevelopmentEnvironmentSection(internetBankingSystem, Format.AsciiDoc,
                                                      "Here is some information about how to set up a development environment for the Internet Banking System...\n" +
                                                      "image::embed:DevelopmentDeployment[]");
            template.AddDeploymentSection(internetBankingSystem, Format.AsciiDoc,
                                          "Here is some information about the live deployment environment for the Internet Banking System...\n" +
                                          "image::embed:LiveDeployment[]");

            return(workspace);
        }
        public void Test_AddNearestNeightbours_DoesNothing_WhenANullElementIsSpecified()
        {
            view.AddNearestNeighbours(null);

            Assert.AreEqual(1, view.Elements.Count);
        }
        private const string DATABASE_TAG = "database";                      // analizar el uso



        static void Main(string[] args)
        {
            // Crear el nuevo espacio de trabajo
            Workspace workspace = new Workspace("Arquitectura de Software - Plataforma de Gestion y Monitoreo de Transporte de Carga", "Diseño de la arquitectura de software de proyectos de transformacion digital");
            Model     model     = workspace.Model;

            model.Enterprise = new Enterprise("Transport Manangement System");
            // Agregar los elementos que contendra el sistema

            Person userCompany  = model.AddPerson(Location.External, "Empresa", "Empresa que adquiere los servicios de la plataforma de gestion y seguimiento de transporte de carga");
            Person userDriver   = model.AddPerson(Location.External, "Chofer", "Persona encargada que transporta la carga de los clientes administrando el flujo de la operacion");
            Person userOperator = model.AddPerson(Location.External, "Operador", "Persona encargada de adminstrar y monitorear las operaciones");
            Person userClient   = model.AddPerson(Location.External, "Cliente", "Persona interesada en realizar el seguimiento de su carga");
            //

            SoftwareSystem tmsSoftwareSystem = model.AddSoftwareSystem(Location.Internal, "TMS Generico", "Plataforma de Gestion y Seguimiento del transporte y logistica de Carga a Nivel Nacional");

            SoftwareSystem odooErpSoftwareSystem            = model.AddSoftwareSystem(Location.Internal, "Odoo Sh", "ERP: Sistema de Planificacion de Recursos Empresariales");
            SoftwareSystem mailServerSoftwareSystem         = model.AddSoftwareSystem(Location.Internal, "Servidor de Correos", "Servidor de Correos Interno Microsoft Exchange");
            SoftwareSystem fcmSoftwareSystem                = model.AddSoftwareSystem(Location.Internal, "Firebase Cloud Messaging ", "Sistema de mensajeria en tiempo real multiplaforma ofrecido por Google");
            SoftwareSystem azureBlobStorageSoftwareSystem   = model.AddSoftwareSystem(Location.Internal, "Azure Blob Storage", "Servidor de Almacenamiento de archivos en la nube de Microsft Azure");
            SoftwareSystem googlMapsPlatoformSoftwareSystem = model.AddSoftwareSystem(Location.Internal, "Google Maps Plataform", "Plataforma web que ofrece un conjunto de APIs (Aplication Interface Programming) para la gestion de mapas, rutas, direcciones, etc. Soportado por Google");

            odooErpSoftwareSystem.AddTags(EXISTS_SYSTEM_TAG);
            mailServerSoftwareSystem.AddTags(EXISTS_SYSTEM_TAG);
            fcmSoftwareSystem.AddTags(EXISTS_SYSTEM_TAG);
            azureBlobStorageSoftwareSystem.AddTags(EXISTS_SYSTEM_TAG);
            googlMapsPlatoformSoftwareSystem.AddTags(EXISTS_SYSTEM_TAG);

            tmsSoftwareSystem.Uses(odooErpSoftwareSystem, "Integra la informacion contable de las operaciones de carga");
            tmsSoftwareSystem.Uses(fcmSoftwareSystem, "Administra notificaciones y mensajes en tiempo real");
            tmsSoftwareSystem.Uses(azureBlobStorageSoftwareSystem, "Administra los archivos generados por el sistema");
            tmsSoftwareSystem.Uses(googlMapsPlatoformSoftwareSystem, "Integra los mapas en las aplicaciones");
            tmsSoftwareSystem.Uses(mailServerSoftwareSystem, "Envia correos electronicos usando");

            fcmSoftwareSystem.Delivers(userDriver, "Envia notificaciones push a la aplicación movil");
            mailServerSoftwareSystem.Delivers(userClient, "Envia Correo electronico a");

            userCompany.Uses(tmsSoftwareSystem, "Adquiere los servicios de la plataforma, administra y registra sus propias operaciones, choferes, clientes");
            userDriver.Uses(tmsSoftwareSystem, "Oferta sus servicios y administra el flujo de la operacion");
            userOperator.Uses(tmsSoftwareSystem, "Adminstrar y monitorear las operaciones, oportunidades de carga, operaciones, rutas,  clientes y operadores");
            userClient.Uses(tmsSoftwareSystem, "Administra sus operaciones y cotizaciones de nuevos servicios");


            // Contenendores
            Container mobileApp = tmsSoftwareSystem.AddContainer("Mobile App", "Provee un conjunto de funcionalidades a los choferes como: postulaciones, notificaciones de posibilidades carga,  gestion de operaciones, entre otros", "Flutter");

            mobileApp.AddTags(MOBILE_APP_TAG);

            Container spaOperations = tmsSoftwareSystem.AddContainer("Single-Page Application (Portal Operaciones)", "Provee las funcionalidades de gestion y monitoreo operaciones, oportunidades, rutas de entre otras atraves del navegador web", "Javascript y Angular 9");

            spaOperations.AddTags(SINGLE_PAGE_APPLICATION_TAG);

            Container spaClients = tmsSoftwareSystem.AddContainer("Single-Page Application (Portal Clientes)", "Provee las funcionalidades de seguimiento de operaciones y cotizaciones atraves del navegador web", "Javascript y Angular 9");

            spaClients.AddTags(SINGLE_PAGE_APPLICATION_TAG);

            Container webApplication = tmsSoftwareSystem.AddContainer("Web Application", "Entrega el contenido estático y las Single-Page Application de los Portales de Operaciones y Clientes", "NodeJs y Express Framework");

            Container apiTmsServicesApplication = tmsSoftwareSystem.AddContainer("API TMS Application", "Provee las funcionalidades de gestion de informacion para los portales via JSON/HTTPS API", "NodeJs y Express Framework");

            Container apiAppServicesApplication = tmsSoftwareSystem.AddContainer("API Mobile Application", "Provee las funcionalidades de gestion de informacion para la aplicacion movil via JSON/HTTPS API", "NodeJs y Express Framework");

            Container database = tmsSoftwareSystem.AddContainer("Database", "Almacena y Registra la informacion de la gestion de operaciones y procesos asociados como: Oportunidades, Postulaciones, Autenticacion de Usuarios, etc.", "Microsoft Azure SQL Database");

            database.AddTags(DATABASE_TAG);

            userDriver.Uses(mobileApp, "Visualiza las oportunidades, operaciones, beneficios entre usando", "Flutter");
            userOperator.Uses(webApplication, "Visita globaltms.la usando", "HTTPS");
            userCompany.Uses(webApplication, "Visita globaltms.la usando", "HTTPS");
            userClient.Uses(webApplication, "Visita globaltms.la usando", "HTTPS");

            userCompany.Uses(spaOperations, "Administrar sus propias oportunidades, operaciones, rutas, clientes, choferes, entre otros. Usando", "HTTPS");
            userOperator.Uses(spaOperations, "Visualiza las oportunidades, operaciones, rutas, clientes, choferes, entre otros. Usando", "HTTPS");
            userClient.Uses(spaClients, "Visualiza las operaciones y cotizaciones de nuevos servicios usando", "HTTPS");

            webApplication.Uses(spaClients, "Entrega al navegador web del cliente");
            webApplication.Uses(spaOperations, "Entrega al navegador web del operador");

            spaClients.Uses(googlMapsPlatoformSoftwareSystem, "Integra Mapa de Google en la Aplicacion Web", "HTTPS/XML");
            spaOperations.Uses(googlMapsPlatoformSoftwareSystem, "Integra Mapa de Google en la Aplicacion Web", "HTTPS/XML");
            mobileApp.Uses(googlMapsPlatoformSoftwareSystem, "Integra Mapa de Google en la Aplicacion Movil", "HTTPS/XML");

            apiAppServicesApplication.Uses(database, "Lee y Escribe en", "Tedious MSSQL");
            apiTmsServicesApplication.Uses(database, "Lee y Escribe en", "Tedious MSSQL");

            apiAppServicesApplication.Uses(azureBlobStorageSoftwareSystem, "Administrar archivos en la nube usando", "HTTPS");
            apiTmsServicesApplication.Uses(azureBlobStorageSoftwareSystem, "Administrar archivos en la nube usando", "HTTPS");

            apiTmsServicesApplication.Uses(mailServerSoftwareSystem, "Envia correos electronicos usando", "SMTP");
            apiTmsServicesApplication.Uses(odooErpSoftwareSystem, "Realiza solicitudes a la API", "HTTP/XML-RPC/JSON-RPC");
            apiTmsServicesApplication.Uses(fcmSoftwareSystem, "Emision de mensajes del servidor usando", "HTTPS/JSON");
            fcmSoftwareSystem.Uses(mobileApp, "Realiza difusion de los mensajes proveidos por el servidor usando", "HTTPS/JSON");

            // EVENTUAL (HASTA AGREGAR LOS COMPONENTES), modificar al momento de agregar los componentes
            //spaClients.Uses(apiTmsServicesApplication, "Realiza solicitudes a la API", "HTTPS/JSON");
            //spaOperations.Uses(apiTmsServicesApplication, "Realiza solicitudes a la API", "HTTPS/JSON");
            //mobileApp.Uses(apiAppServicesApplication, "Realiza solicitudes a la API", "HTTPS/JSON");



            // Componentes (API APP SERVICES)
            string expressApiController = "Express API Controller";
            // Controllers
            Component userControllerMobile = apiAppServicesApplication.AddComponent("User Controller", "Permite a los usuarios autenticarse para acceder a la aplicacion movil", "Express API Controller");

            Component carrierControllerMobile       = apiAppServicesApplication.AddComponent("Carrier Controller", "Permite gestionar los datos relacionados a su perfil", "Express API Controller");
            Component unitTransportControllerMobile = apiAppServicesApplication.AddComponent("UnitTransport Controller", "Permite gestionar los datos relacionados a su unidad de transporte", "Express API Controller");
            Component loadingOrderControllerMobile  = apiAppServicesApplication.AddComponent("LoadingOrder Controller", "Permite gestionar las operaciones vinculadas como tambien el flujo de cada una de ellas", "Express API Controller");

            // Services
            Component servicePassportAuthenticationMobile = apiAppServicesApplication.AddComponent("Module Passport Authentication", "Provee autenticacion segura del lado del servidor", "Node Module");
            Component serviceAzureBlobStorageMobile       = apiAppServicesApplication.AddComponent("Service Azure Blob Storage", "Provee los metodos para administrar archivos a la nube de Azure", "Node Module");

            // Business
            Component userBusinessMobile          = apiAppServicesApplication.AddComponent("User Business", "Provee funcionalidades de administracion de usuarios", "Javascript Class");
            Component carrierBusinessMobile       = apiAppServicesApplication.AddComponent("Carrier Business", "Provee funcionalidades de gestion de informacion de los choferes", "Javascript Class");
            Component unitTransportBusinessMobile = apiAppServicesApplication.AddComponent("UnitTransport Business", "Provee funcionalidades de gestion de informacion de las unidades de transporte", "Javascript Class");
            Component loadingOrderBusinessMobile  = apiAppServicesApplication.AddComponent("LoadingOrder Business", "Provee funcionalidades de gestion del flujo de datos de las ordenes de carga", "Javascript Class");

            // Conexion a Base de datos
            Component moduleSequelizeOrmAppServicesMobile = apiAppServicesApplication.AddComponent("Module Sequelize ORM", "Provee una capa de abstraccion para la conexiona a la base de datos", "Node Module");


            // Relations
            apiAppServicesApplication.Components.Where(comp => expressApiController.Equals(comp.Technology))
            .ToList()
            .ForEach(comp => mobileApp.Uses(comp, "Realiza solicitudes a la API", "HTTPS/JSON"));
            userControllerMobile.Uses(servicePassportAuthenticationMobile, "Usa");
            carrierControllerMobile.Uses(serviceAzureBlobStorageMobile, "Usa");
            unitTransportControllerMobile.Uses(serviceAzureBlobStorageMobile, "Usa");
            loadingOrderControllerMobile.Uses(serviceAzureBlobStorageMobile, "Usa");

            serviceAzureBlobStorageMobile.Uses(azureBlobStorageSoftwareSystem, "Usa", "HTTPS");

            userControllerMobile.Uses(userBusinessMobile, "Usa");
            carrierControllerMobile.Uses(carrierBusinessMobile, "Usa");
            unitTransportControllerMobile.Uses(unitTransportBusinessMobile, "Usa");
            loadingOrderControllerMobile.Uses(loadingOrderBusinessMobile, "Usa");

            userBusinessMobile.Uses(moduleSequelizeOrmAppServicesMobile, "Usa");
            carrierBusinessMobile.Uses(moduleSequelizeOrmAppServicesMobile, "Usa");
            unitTransportBusinessMobile.Uses(moduleSequelizeOrmAppServicesMobile, "Usa");
            loadingOrderBusinessMobile.Uses(moduleSequelizeOrmAppServicesMobile, "Usa");

            moduleSequelizeOrmAppServicesMobile.Uses(database, "Lee y Escribe en", "MSSQL Tedious");



            // Componentes (API TMS SERVICES)

            // Controllers
            Component userControllerTms          = apiTmsServicesApplication.AddComponent("User Controller", "Permite a los usuarios autenticarse para acceder a los portales web", "Express API Controller");
            Component carrierControllerTms       = apiTmsServicesApplication.AddComponent("Carrier Controller", "Permite gestionar los datos relacionados al perfil del chofer", "Express API Controller");
            Component unitTransportControllerTms = apiTmsServicesApplication.AddComponent("UnitTransport Controller", "Permite gestionar los datos relacionados a su unidad de transporte", "Express API Controller");
            Component loadingOrderControllerTms  = apiTmsServicesApplication.AddComponent("LoadingOrder Controller", "Permite administrar las ordenes de carga", "Express API Controller");
            Component opportunityControllerTms   = apiTmsServicesApplication.AddComponent("Opportunity Controller", "Permite administrar las oportunidades de carga", "Express API Controller");
            Component operationControllerTms     = apiTmsServicesApplication.AddComponent("Operation Controller", "Permite administrar las operaciones y su flujo", "Express API Controller");
            Component clientControllerTms        = apiTmsServicesApplication.AddComponent("Client Controller", "Permite gestionar los datos de clientes", "Express API Controller");

            // Services
            Component servicePassportAuthenticationTms = apiTmsServicesApplication.AddComponent("Module Passport Authentication", "Provee seguridad en autenticacion de usuario del lado del servidor", "Node Module");
            Component serviceAzureBlobStorageTms       = apiTmsServicesApplication.AddComponent("Service Azure Blob Storage", "Provee los metodos para administrar archivos a la nube de Azure", "Node Module");
            Component serviceFirebaseCloudMessagingTms = apiTmsServicesApplication.AddComponent("Service Firebase Cloud Messaging", "Provee funcionalidades para emitir/recepcionar notificaciones en tiempo real", "API Firebase");
            Component serviceOdooApiTms = apiTmsServicesApplication.AddComponent("Service Odoo API", "Provee funcionalidades de integracion con la base de datos de Odoo", "Node Module");
            Component serviceMailerTms  = apiTmsServicesApplication.AddComponent("Service NodeMailer", "Provee funcionalidades para enviar correos electronicos", "Node Module");

            // Business
            Component userBusinessTms          = apiTmsServicesApplication.AddComponent("User Business", "Provee funcionalidades de administracion de usuarios", "Javascript Class");
            Component carrierBusinessTms       = apiTmsServicesApplication.AddComponent("Carrier Business", "Provee funcionalidades de gestion de informacion de los choferes", "Javascript Class");
            Component unitTransportBusinessTms = apiTmsServicesApplication.AddComponent("UnitTransport Business", "Provee funcionalidades de gestion de informacion de las unidades de transporte", "Javascript Class");
            Component opportunityBusinessTms   = apiTmsServicesApplication.AddComponent("Opportunity Business", "Provee funcionalidades de gestion del reclutamiento de choferes para las operaciones", "Javascript Class");
            Component operationBusinessTms     = apiTmsServicesApplication.AddComponent("Operation Business", "Provee funcionalidades de gestion y seguimiento de operaciones", "Javascript Class");
            Component clientBusinessTms        = apiTmsServicesApplication.AddComponent("Client Business", "Provee funcionalidades de gestion de los clientes", "Javascript Class");
            Component loadingOrderBusinessTms  = apiTmsServicesApplication.AddComponent("LoadingOrder Business", "Provee funcionalidades de gestion del flujo de datos de las ordenes de carga", "Javascript Class");

            // Conexion a Base de datos
            Component moduleSequelizeOrmAppServicesTms = apiTmsServicesApplication.AddComponent("Module Sequelize ORM", "Provee una capa de abstraccion para la conexiona a la base de datos", "Node Module");


            // Relations
            apiTmsServicesApplication.Components.Where(comp => expressApiController.Equals(comp.Technology))
            .ToList()
            .ForEach(comp => spaOperations.Uses(comp, "Realiza solicitudes a la API", "HTTPS/JSON"));


            List <string> excludeControllersForClients = new List <string>
            {
                "Carrier Controller", "UnitTransport Controller", "Opportunity Controller"
            };

            apiTmsServicesApplication.Components.Where(comp => expressApiController.Equals(comp.Technology))
            .ToList()
            .ForEach(comp =>
            {
                if (!excludeControllersForClients.Contains(comp.Name))
                {
                    spaClients.Uses(comp, "Realiza solicitudes a la API", "HTTPS/JSON");
                }
            });

            userControllerTms.Uses(servicePassportAuthenticationTms, "Usa");

            carrierControllerTms.Uses(serviceFirebaseCloudMessagingTms, "Usa");

            unitTransportControllerTms.Uses(serviceFirebaseCloudMessagingTms, "Usa");

            loadingOrderControllerTms.Uses(serviceAzureBlobStorageTms, "Usa");
            loadingOrderControllerTms.Uses(serviceFirebaseCloudMessagingTms, "Usa");
            loadingOrderControllerTms.Uses(serviceOdooApiTms, "Usa");

            operationControllerTms.Uses(serviceFirebaseCloudMessagingTms, "Usa");
            operationControllerTms.Uses(serviceOdooApiTms, "Usa");

            opportunityControllerTms.Uses(serviceFirebaseCloudMessagingTms, "Usa");

            clientControllerTms.Uses(serviceMailerTms, "Usa");


            serviceAzureBlobStorageTms.Uses(azureBlobStorageSoftwareSystem, "Usa", "HTTPS");
            serviceMailerTms.Uses(mailServerSoftwareSystem, "Envia correos electronicos usando", "SMTP");
            serviceOdooApiTms.Uses(odooErpSoftwareSystem, "Usa", "HTTP/XML-RPC/JSON-RPC");
            serviceFirebaseCloudMessagingTms.Uses(fcmSoftwareSystem, "Usa", "HTTPS");
            serviceAzureBlobStorageTms.Uses(azureBlobStorageSoftwareSystem, "Usa", "HTTPS");


            userControllerTms.Uses(userBusinessTms, "Usa");
            carrierControllerTms.Uses(carrierBusinessTms, "Usa");
            unitTransportControllerTms.Uses(unitTransportBusinessTms, "Usa");
            loadingOrderControllerTms.Uses(loadingOrderBusinessTms, "Usa");
            operationControllerTms.Uses(operationBusinessTms, "Usa");
            opportunityControllerTms.Uses(opportunityBusinessTms, "Usa");
            clientControllerTms.Uses(clientBusinessTms, "Usa");


            userBusinessTms.Uses(moduleSequelizeOrmAppServicesTms, "Usa");
            carrierBusinessTms.Uses(moduleSequelizeOrmAppServicesTms, "Usa");
            unitTransportBusinessTms.Uses(moduleSequelizeOrmAppServicesTms, "Usa");
            loadingOrderBusinessTms.Uses(moduleSequelizeOrmAppServicesTms, "Usa");
            opportunityBusinessTms.Uses(moduleSequelizeOrmAppServicesTms, "Usa");
            operationBusinessTms.Uses(moduleSequelizeOrmAppServicesTms, "Usa");
            clientBusinessTms.Uses(moduleSequelizeOrmAppServicesTms, "Usa");

            moduleSequelizeOrmAppServicesTms.Uses(database, "Lee y Escribe en", "MSSQL Tedious");



            model.AddImplicitRelationships();


            // Definir la visualizacion de los diagramas
            ViewSet           views             = workspace.Views;
            SystemContextView systemContextView = views.CreateSystemContextView(tmsSoftwareSystem, "Contexto de Sistema", "Diagrama de Contexto de Sistema (Nivel 1)");

            systemContextView.EnterpriseBoundaryVisible = false;
            systemContextView.AddNearestNeighbours(tmsSoftwareSystem);
            systemContextView.PaperSize = PaperSize.A5_Landscape;

            /*contextView.AddAllSoftwareSystems();
             * contextView.AddAllPeople();*/

            ContainerView containerView = views.CreateContainerView(tmsSoftwareSystem, "Contenedores de Sistema", "Diagrama de contenedores de Sistema (Nivel 2)");

            containerView.Add(userOperator);
            containerView.Add(userClient);
            containerView.Add(userCompany);
            containerView.Add(userDriver);
            containerView.AddAllContainers();
            containerView.AddAllSoftwareSystems();
            containerView.Remove(tmsSoftwareSystem);

            // Componentes for API Mobile Application
            ComponentView componentMobileView = views.CreateComponentView(apiAppServicesApplication, "Componentes de Sistema - API Mobile", "Diagrama de Componentes de Sistema (Nivel 3)");

            componentMobileView.Add(mobileApp);
            componentMobileView.Add(azureBlobStorageSoftwareSystem);
            componentMobileView.Add(database);
            componentMobileView.AddAllComponents();
            componentMobileView.PaperSize = PaperSize.A5_Landscape;

            // Componentes for API TMS Application
            ComponentView componentTMSView = views.CreateComponentView(apiTmsServicesApplication, "Componentes de Sistema - API TMS", "Diagrama de Componentes de Sistema (Nivel 3)");

            componentTMSView.Add(spaClients);
            componentTMSView.Add(spaOperations);
            componentTMSView.Add(azureBlobStorageSoftwareSystem);
            componentTMSView.Add(mailServerSoftwareSystem);
            componentTMSView.Add(odooErpSoftwareSystem);
            componentTMSView.Add(fcmSoftwareSystem);
            componentTMSView.Add(database);
            componentTMSView.AddAllComponents();
            componentTMSView.PaperSize = PaperSize.A5_Landscape;

            // Agregar algo de documentacion
            StructurizrDocumentationTemplate template = new StructurizrDocumentationTemplate(workspace);

            template.AddContextSection(tmsSoftwareSystem, Format.Markdown, "Definiendo el contexto del sistema de software\n![](embed:SystemContext)");

            // agregando estilos personalizados
            Styles styles = views.Configuration.Styles;

            styles.Add(new ElementStyle(Tags.SoftwareSystem)
            {
                Background = "#1168bd", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(Tags.Person)
            {
                Background = "#08427b", Color = "#ffffff", Shape = Shape.Person
            });
            styles.Add(new ElementStyle(Tags.Container)
            {
                Background = "#438dd5", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(Tags.Component)
            {
                Background = "#85bbf0", Color = "#000000"
            });
            styles.Add(new ElementStyle(EXISTS_SYSTEM_TAG)
            {
                Background = "#999999", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(MOBILE_APP_TAG)
            {
                Shape = Shape.MobileDeviceLandscape
            });
            styles.Add(new ElementStyle(SINGLE_PAGE_APPLICATION_TAG)
            {
                Shape = Shape.WebBrowser
            });
            styles.Add(new ElementStyle(DATABASE_TAG)
            {
                Shape = Shape.Cylinder
            });

            // cargar el documento actual (formato JSON)
            updateWorkspaceToStructurizr(workspace);



            Console.WriteLine("Generated Diagram Sucessfully!");
        }
Example #6
0
        private static Workspace Create(bool usePaidFeatures)
        {
            Workspace workspace = new Workspace("Big Bank plc", "This is an example workspace to illustrate the key features of Structurizr, based around a fictional online banking system.");
            Model     model     = workspace.Model;
            ViewSet   views     = workspace.Views;

            model.Enterprise = new Enterprise("Big Bank plc");

            // people and software systems
            Person customer = model.AddPerson(Location.External, "Customer", "A customer of the bank.");

            SoftwareSystem internetBankingSystem = model.AddSoftwareSystem(Location.Internal, "Internet Banking System", "Allows customers to view information about their bank accounts and make payments.");

            customer.Uses(internetBankingSystem, "Uses");

            SoftwareSystem mainframeBankingSystem = model.AddSoftwareSystem(Location.Internal, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.");

            internetBankingSystem.Uses(mainframeBankingSystem, "Uses");

            SoftwareSystem atm = model.AddSoftwareSystem(Location.Internal, "ATM", "Allows customers to withdraw cash.");

            atm.Uses(mainframeBankingSystem, "Uses");
            customer.Uses(atm, "Withdraws cash using");

            Person bankStaff = model.AddPerson(Location.Internal, "Bank Staff", "Staff within the bank.");

            bankStaff.Uses(mainframeBankingSystem, "Uses");

            // containers
            Container webApplication = internetBankingSystem.AddContainer("Web Application", "Provides all of the Internet banking functionality to customers.", "Java and Spring MVC");
            Container database       = internetBankingSystem.AddContainer("Database", "Stores interesting data.", "Relational Database Schema");

            database.AddTags(DatabaseTag);

            customer.Uses(webApplication, "Uses", "HTTPS");
            webApplication.Uses(database, "Reads from and writes to", "JDBC");
            webApplication.Uses(mainframeBankingSystem, "Uses", "XML/HTTPS");

            // components
            // - for a real-world software system, you would probably want to extract the components using
            // - static analysis/reflection rather than manually specifying them all
            Component homePageController           = webApplication.AddComponent("Home Page Controller", "Serves up the home page.", "Spring MVC Controller");
            Component signinController             = webApplication.AddComponent("Sign In Controller", "Allows users to sign in to the Internet Banking System.", "Spring MVC Controller");
            Component accountsSummaryController    = webApplication.AddComponent("Accounts Summary Controller", "Provides customers with an summary of their bank accounts.", "Spring MVC Controller");
            Component securityComponent            = webApplication.AddComponent("Security Component", "Provides functionality related to signing in, changing passwords, etc.", "Spring Bean");
            Component mainframeBankingSystemFacade = webApplication.AddComponent("Mainframe Banking System Facade", "A facade onto the mainframe banking system.", "Spring Bean");

            webApplication.Components.Where(c => "Spring MVC Controller".Equals(c.Technology)).ToList().ForEach(c => customer.Uses(c, "Uses", "HTTPS"));
            signinController.Uses(securityComponent, "Uses");
            accountsSummaryController.Uses(mainframeBankingSystemFacade, "Uses");
            securityComponent.Uses(database, "Reads from and writes to", "JDBC");
            mainframeBankingSystemFacade.Uses(mainframeBankingSystem, "Uses", "XML/HTTPS");

            // deployment nodes and container instances
            DeploymentNode developerLaptop = model.AddDeploymentNode("Developer Laptop", "A developer laptop.", "Windows 7 or 10");

            developerLaptop.AddDeploymentNode("Docker Container - Web Server", "A Docker container.", "Docker")
            .AddDeploymentNode("Apache Tomcat", "An open source Java EE web server.", "Apache Tomcat 8.x", 1, DictionaryUtils.Create("Xmx=512M", "Xms=1024M", "Java Version=8"))
            .Add(webApplication);

            developerLaptop.AddDeploymentNode("Docker Container - Database Server", "A Docker container.", "Docker")
            .AddDeploymentNode("Database Server", "A development database.", "Oracle 12c")
            .Add(database);

            DeploymentNode liveWebServer = model.AddDeploymentNode("bigbank-web***", "A web server residing in the web server farm, accessed via F5 BIG-IP LTMs.", "Ubuntu 16.04 LTS", 8, DictionaryUtils.Create("Location=London"));

            liveWebServer.AddDeploymentNode("Apache Tomcat", "An open source Java EE web server.", "Apache Tomcat 8.x", 1, DictionaryUtils.Create("Xmx=512M", "Xms=1024M", "Java Version=8"))
            .Add(webApplication);

            DeploymentNode primaryDatabaseServer = model.AddDeploymentNode("bigbank-db01", "The primary database server.", "Ubuntu 16.04 LTS", 1, DictionaryUtils.Create("Location=London"))
                                                   .AddDeploymentNode("Oracle - Primary", "The primary, live database server.", "Oracle 12c");

            primaryDatabaseServer.Add(database);

            DeploymentNode secondaryDatabaseServer = model.AddDeploymentNode("bigbank-db02", "The secondary database server.", "Ubuntu 16.04 LTS", 1, DictionaryUtils.Create("Location=Reading"))
                                                     .AddDeploymentNode("Oracle - Secondary", "A secondary, standby database server, used for failover purposes only.", "Oracle 12c");
            ContainerInstance secondaryDatabase = secondaryDatabaseServer.Add(database);

            model.Relationships.Where(r => r.Destination.Equals(secondaryDatabase)).ToList().ForEach(r => r.AddTags("Failover"));
            Relationship dataReplicationRelationship = primaryDatabaseServer.Uses(secondaryDatabaseServer, "Replicates data to", "");

            secondaryDatabase.AddTags("Failover");

            // views/diagrams
            EnterpriseContextView enterpriseContextView = views.CreateEnterpriseContextView("SystemLandscape", "The system landscape diagram for Big Bank plc.");

            enterpriseContextView.AddAllElements();
            enterpriseContextView.PaperSize = PaperSize.A5_Landscape;

            SystemContextView systemContextView = views.CreateSystemContextView(internetBankingSystem, "SystemContext", "The system context diagram for the Internet Banking System.");

            systemContextView.AddNearestNeighbours(internetBankingSystem);
            systemContextView.PaperSize = PaperSize.A5_Landscape;

            ContainerView containerView = views.CreateContainerView(internetBankingSystem, "Containers", "The container diagram for the Internet Banking System.");

            containerView.Add(customer);
            containerView.AddAllContainers();
            containerView.Add(mainframeBankingSystem);
            containerView.PaperSize = PaperSize.A5_Landscape;

            ComponentView componentView = views.CreateComponentView(webApplication, "Components", "The component diagram for the Web Application");

            componentView.AddAllContainers();
            componentView.AddAllComponents();
            componentView.Add(customer);
            componentView.Add(mainframeBankingSystem);
            componentView.PaperSize = PaperSize.A5_Landscape;

            if (usePaidFeatures)
            {
                // dynamic diagrams, deployment diagrams and corporate branding are not available with the Free Plan
                DynamicView dynamicView = views.CreateDynamicView(webApplication, "SignIn", "Summarises how the sign in feature works.");
                dynamicView.Add(customer, "Requests /signin from", signinController);
                dynamicView.Add(customer, "Submits credentials to", signinController);
                dynamicView.Add(signinController, "Calls isAuthenticated() on", securityComponent);
                dynamicView.Add(securityComponent, "select * from users u where username = ?", database);
                dynamicView.PaperSize = PaperSize.A5_Landscape;

                DeploymentView developmentDeploymentView = views.CreateDeploymentView(internetBankingSystem, "DevelopmentDeployment", "An example development deployment scenario for the Internet Banking System.");
                developmentDeploymentView.Add(developerLaptop);
                developmentDeploymentView.PaperSize = PaperSize.A5_Landscape;

                DeploymentView liveDeploymentView = views.CreateDeploymentView(internetBankingSystem, "LiveDeployment", "An example live deployment scenario for the Internet Banking System.");
                liveDeploymentView.Add(liveWebServer);
                liveDeploymentView.Add(primaryDatabaseServer);
                liveDeploymentView.Add(secondaryDatabaseServer);
                liveDeploymentView.Add(dataReplicationRelationship);
                liveDeploymentView.PaperSize = PaperSize.A5_Landscape;
            }

            // colours, shapes and other diagram styling
            Styles styles = views.Configuration.Styles;

            styles.Add(new ElementStyle(Tags.Element)
            {
                Color = "#ffffff"
            });
            styles.Add(new ElementStyle(Tags.SoftwareSystem)
            {
                Background = "#1168bd"
            });
            styles.Add(new ElementStyle(Tags.Container)
            {
                Background = "#438dd5"
            });
            styles.Add(new ElementStyle(Tags.Component)
            {
                Background = "#85bbf0", Color = "#000000"
            });
            styles.Add(new ElementStyle(Tags.Person)
            {
                Background = "#08427b", Shape = Shape.Person
            });
            styles.Add(new ElementStyle(DatabaseTag)
            {
                Shape = Shape.Cylinder
            });
            styles.Add(new ElementStyle("Failover")
            {
                Opacity = 25
            });
            styles.Add(new RelationshipStyle("Failover")
            {
                Opacity = 25, Position = 70
            });

            // documentation
            // - usually the documentation would be included from separate Markdown/AsciiDoc files, but this is just an example
            StructurizrDocumentationTemplate template = new StructurizrDocumentationTemplate(workspace);

            template.AddContextSection(internetBankingSystem, Format.Markdown,
                                       "Here is some context about the Internet Banking System...\n" +
                                       "![](embed:EnterpriseContext)\n" +
                                       "![](embed:SystemContext)\n" +
                                       "### Internet Banking System\n...\n" +
                                       "### Mainframe Banking System\n...\n");
            template.AddContainersSection(internetBankingSystem, Format.Markdown,
                                          "Here is some information about the containers within the Internet Banking System...\n" +
                                          "![](embed:Containers)\n" +
                                          "### Web Application\n...\n" +
                                          "### Database\n...\n");
            template.AddComponentsSection(webApplication, Format.Markdown,
                                          "Here is some information about the Web Application...\n" +
                                          "![](embed:Components)\n" +
                                          "### Sign in process\n" +
                                          "Here is some information about the Sign In Controller, including how the sign in process works...\n" +
                                          "![](embed:SignIn)");
            template.AddDevelopmentEnvironmentSection(internetBankingSystem, Format.AsciiDoc,
                                                      "Here is some information about how to set up a development environment for the Internet Banking System...\n" +
                                                      "image::embed:DevelopmentDeployment[]");
            template.AddDeploymentSection(internetBankingSystem, Format.AsciiDoc,
                                          "Here is some information about the live deployment environment for the Internet Banking System...\n" +
                                          "image::embed:LiveDeployment[]");

            return(workspace);
        }
Example #7
0
        private void BuildC4Model()
        {
            // Add stakeholders en Systemen
            SoftwareSystem boekhoudSysteem = model.AddSoftwareSystem(Location.Internal, "Boekhoudsysteem", "Boekhoudsysteem voor midden en kleinbedrijf en ZZP'er");

            SoftwareSystem itsmSysteem = model.AddSoftwareSystem(Location.Internal, "ITSM Systeem", "Interne CRM applicatie");

            itsmSysteem.AddTags(InternalSystemTag);
            boekhoudSysteem.Uses(itsmSysteem, "Haalt abonnement gegevens op");

            SoftwareSystem website = model.AddSoftwareSystem(Location.Internal, "Website", $"publieke website van {BedrijfsNaam}");

            website.AddTags(WebBrowserTag);
            website.Uses(itsmSysteem, "Registreert een abonnement");

            SoftwareSystem webshop = model.AddSoftwareSystem(Location.External, "Webshop", $"Webshopkoppeling names klant met Boekhoudsysteem");

            webshop.AddTags(ExternalSystemTag);
            boekhoudSysteem.Uses(webshop, "krijgt gegevens van");

            SoftwareSystem bank = model.AddSoftwareSystem(Location.External, "Bank", $"Bankkoppeling names klant met Boekhoudsysteem");

            bank.AddTags(ExternalSystemTag);
            boekhoudSysteem.Uses(bank, "krijgt gegevens van");

            Person hoofdgebruiker = model.AddPerson(Location.External, "Hoofdgebruiker", "De gebruiker van de klant die het abonnenement heeft afgesloten");

            hoofdgebruiker.Uses(boekhoudSysteem, Gebruikt);
            hoofdgebruiker.Uses(website, Gebruikt);

            Person gebruiker = model.AddPerson(Location.External, "Gebruiker", "De medewerker van de klant");

            gebruiker.Uses(boekhoudSysteem, Gebruikt);

            Person accountant = model.AddPerson(Location.External, "Accountant", "De accountant van de klant");

            accountant.Uses(boekhoudSysteem, Gebruikt);
            hoofdgebruiker.InteractsWith(accountant, "Vraagt controle aan bij");

            Person helpdesk = model.AddPerson(Location.Internal, "Helpdeskmedewerker", $"Helpdeskmedewerker van {BedrijfsNaam}");

            helpdesk.Uses(boekhoudSysteem, Gebruikt);
            helpdesk.Uses(itsmSysteem, Gebruikt);
            hoofdgebruiker.InteractsWith(helpdesk, "Vraagt hulp van");

            // Extra diagram: Systeemlandschap
            SystemLandscapeView systemLandscapeView = views.CreateSystemLandscapeView("SystemLandscape", "System Context diagram Boekhoudsysteem.");

            systemLandscapeView.AddAllElements();
            systemLandscapeView.EnableAutomaticLayout();

            // containers
            Container coreModule = boekhoudSysteem.AddContainer("Core Module", "Basis module voor inrichting, gebruikers", "C#");

            coreModule.AddTags(Tags.Container);
            coreModule.Uses(itsmSysteem, "krijgt gegevens van");

            Container bankModule = boekhoudSysteem.AddContainer("Bank Module", "Importeren van betaalgegevens", "C#");

            bankModule.AddTags(Tags.Container);
            bankModule.Uses(bank, "krijgt gegevens van");

            Container koppelingModule = boekhoudSysteem.AddContainer("Koppelingen Module", "Module voor inrichten diverse externe koppelingen", "C#");

            koppelingModule.AddTags(Tags.Container);
            koppelingModule.Uses(webshop, "krijgt gegevens van");

            Container boekhoudModule = boekhoudSysteem.AddContainer("Boekhoud Module", "Basis onderdelen van een Boekhoudsysteem zoals dagboeken en rapportages", "C#");

            boekhoudModule.AddTags(Tags.Container);
            boekhoudModule.Uses(webshop, "krijgt gegevens van");

            Container facturatieModule = boekhoudSysteem.AddContainer("Facturatie Module", "Facturatie en Offerte module", "C#");

            facturatieModule.AddTags(Tags.Container);
            facturatieModule.Uses(boekhoudModule, "geeft verkooporders aan");

            Container importModule = boekhoudSysteem.AddContainer("Import Module", "Module voor import en export gegevens", "C#");

            importModule.AddTags(Tags.Container);
            importModule.Uses(boekhoudModule, "geeft relaties aan");
            importModule.Uses(facturatieModule, "geeft artikelen aan");

            hoofdgebruiker.Uses(coreModule, Gebruikt);
            hoofdgebruiker.Uses(boekhoudModule, Gebruikt);
            hoofdgebruiker.Uses(facturatieModule, Gebruikt);
            hoofdgebruiker.Uses(bankModule, Gebruikt);
            hoofdgebruiker.Uses(koppelingModule, Gebruikt);
            hoofdgebruiker.Uses(importModule, Gebruikt);

            gebruiker.Uses(boekhoudModule, Gebruikt);
            gebruiker.Uses(facturatieModule, Gebruikt);
            gebruiker.Uses(bankModule, Gebruikt);

            accountant.Uses(boekhoudModule, Gebruikt);
            helpdesk.Uses(boekhoudModule, Gebruikt);

            Container databaseSystem = boekhoudSysteem.AddContainer("Systeem Database", "Opslag gebruikers, abonnement, administratie gegevens, hashed authentication credentials, access logs, etc.", "Relational Database Schema");

            databaseSystem.AddTags(DatabaseTag);
            coreModule.Uses(databaseSystem, Gebruikt);

            Container databaseAccount = boekhoudSysteem.AddContainer("Boekhouding Database", "Opslag boekhouding per abonnement per administratie", "Relational Database Schema");

            databaseAccount.AddTags(DatabaseTag);
            boekhoudModule.Uses(databaseAccount, Gebruikt);
            facturatieModule.Uses(databaseAccount, Gebruikt);
            bankModule.Uses(databaseAccount, Gebruikt);

            // Components
            Component bankImportView = bankModule.AddComponent("Bank statement Import", "Importscherm bankafschriften", "ASP.Net Webform");

            bankImportView.AddTags(WebBrowserTag);
            Component bankPaymentLogic = bankModule.AddComponent("Payment logic service", "Businesslaag bankafschriften", "C#");

            bankPaymentLogic.AddTags(InternalSystemTag);
            Component bankPaymentData = bankModule.AddComponent("Payment data service", "Datalaag bankafschriften", "C#");

            bankPaymentData.AddTags(InternalSystemTag);

            bankImportView.Uses(bankPaymentLogic, Gebruikt);
            bankPaymentLogic.Uses(bankPaymentData, Gebruikt);
            bankPaymentLogic.Uses(bank, Gebruikt);

            Component bankPaymentView = bankModule.AddComponent("Bank payments", "Betaalopdrachten", "ASP.Net Webform");

            bankPaymentView.AddTags(WebBrowserTag);
            bankPaymentView.Uses(bankPaymentLogic, Gebruikt);

            Component bankInstellingView = bankModule.AddComponent("Instellingen Bankstatements", "Instellingen bankafschriften", "ASP.Net Webform");

            bankInstellingView.AddTags(WebBrowserTag);
            Component bankInstellingLogic = bankModule.AddComponent("Bankinstellingen logic service", "Businesslaag bankinstellingen", "C#");

            bankInstellingLogic.AddTags(InternalSystemTag);
            Component bankInstellingData = bankModule.AddComponent("Bankinstellingen data service", "Datalaag bankinstellingen", "C#");

            bankInstellingData.AddTags(InternalSystemTag);

            bankInstellingView.Uses(bankInstellingLogic, Gebruikt);
            bankInstellingLogic.Uses(bankInstellingData, Gebruikt);

            bankPaymentData.Uses(databaseAccount, "Leest en schrijft naar", "Linq2Sql");
            bankInstellingData.Uses(databaseAccount, "Leest en schrijft naar", "Linq2Sql");

            Component importExportView = importModule.AddComponent("Artikel Import", "Importscherm artikelen", "ASP.Net Webform");

            importExportView.AddTags(WebBrowserTag);
            Component importExportLogic = importModule.AddComponent("Import Export logic service", "Businesslaag import export functionaliteit", "C#");

            importExportLogic.AddTags(InternalSystemTag);
            Component importExportData = importModule.AddComponent("Import Export data service", "Datalaag import export functionaliteit", "C#");

            importExportData.AddTags(InternalSystemTag);

            importExportView.Uses(importExportLogic, Gebruikt);
            importExportLogic.Uses(importExportData, Gebruikt);
            importExportData.Uses(databaseAccount, "Leest en schrijft naar", "Linq2Sql");

            // Add Views
            SystemContextView contextView = views.CreateSystemContextView(boekhoudSysteem, "SystemContext", "System Context diagram Boekhoudsysteem.");

            contextView.AddNearestNeighbours(boekhoudSysteem);
            contextView.EnableAutomaticLayout();

            ContainerView containerView = views.CreateContainerView(boekhoudSysteem, "Containers", "Het container diagram voor het boekhoudsysteem.");

            containerView.EnableAutomaticLayout();
            containerView.Add(hoofdgebruiker);
            containerView.Add(gebruiker);
            containerView.Add(accountant);
            containerView.Add(helpdesk);
            containerView.AddAllContainers();
            containerView.Add(webshop);
            containerView.Add(bank);
            containerView.Add(itsmSysteem);

            ComponentView bankComponentView = views.CreateComponentView(bankModule, "Bank Components", "Component diagram van de Bank module");

            bankComponentView.EnableAutomaticLayout();
            bankComponentView.Add(databaseAccount);
            bankComponentView.AddAllComponents();
            bankComponentView.Add(bank);

            ComponentView importExportComponentView = views.CreateComponentView(importModule, "Import-Export Components", "Component diagram van de Import Export module.");

            importExportComponentView.EnableAutomaticLayout();
            importExportComponentView.Add(databaseAccount);
            importExportComponentView.AddAllComponents();

            // Extra diagram: Deployment
            const string Productie = "Productieomgeving";

            DeploymentNode productieOmgeving = model.AddDeploymentNode(Productie, $"{BedrijfsNaam}", "", $"{BedrijfsNaam} data center");
            DeploymentNode customerComputer  = model.AddDeploymentNode(Productie, "Gebruiker's computer", "", "Microsoft Windows or Apple macOS");

            customerComputer.AddDeploymentNode("Web Browser", "", "Chrome, Firefox, Edge or IE11").Add(boekhoudModule);
            customerComputer.AddTags(WebBrowserTag);

            DeploymentNode productieWebServer = productieOmgeving.AddDeploymentNode($"{BedrijfsNaam}-web***", "Een webserver gehost in een webserver farm", "Windows 2019", 2, DictionaryUtils.Create("Location=Amsterdam"));

            productieWebServer
            .AddDeploymentNode("Microsoft IIS", "Microsoft web server.", "IIS", 1, DictionaryUtils.Create("Xmx=512M", "Xms=1024M", ".Net Framework 4.8"))
            .Add(boekhoudModule);
            customerComputer.Uses(productieWebServer, Gebruikt, "https");

            DeploymentNode primaryDatabaseServer = productieOmgeving
                                                   .AddDeploymentNode($"{BedrijfsNaam}-db01", "Primary database server.", "Windows 2019", 1, DictionaryUtils.Create("Location=Amsterdam"))
                                                   .AddDeploymentNode("SQL Server - Primary", $"Primary, {Productie} databaseserver.", "SqlServer 2017");

            primaryDatabaseServer.Add(databaseSystem);
            primaryDatabaseServer.Add(databaseAccount);

            DeploymentNode failoverDb = productieOmgeving.AddDeploymentNode($"{BedrijfsNaam}-db02", "Secondary database server.", "Windows 2019", 1, DictionaryUtils.Create("Location=Amsterdam"));

            failoverDb.AddTags(FailoverTag);

            DeploymentNode secondaryDatabaseServer = failoverDb.AddDeploymentNode("SQL Server - Secondary", "Secondary, standby database server, alleen voor failover.", "SqlServer 2017");

            secondaryDatabaseServer.AddTags(FailoverTag);

            ContainerInstance secondaryDatabaseSystem  = secondaryDatabaseServer.Add(databaseSystem);
            ContainerInstance secondaryDatabaseAccount = secondaryDatabaseServer.Add(databaseAccount);

            model.Relationships.Where(r => r.Destination.Equals(secondaryDatabaseSystem)).ToList().ForEach(r => r.AddTags(FailoverTag));
            model.Relationships.Where(r => r.Destination.Equals(secondaryDatabaseAccount)).ToList().ForEach(r => r.AddTags(FailoverTag));
            Relationship dataReplicationRelationship = primaryDatabaseServer.Uses(secondaryDatabaseServer, "Replicates data to", "");

            secondaryDatabaseSystem.AddTags(FailoverTag);
            secondaryDatabaseAccount.AddTags(FailoverTag);

            DeploymentView systeemDeploymentView = views.CreateDeploymentView(boekhoudSysteem, Productie, $"De productieomgeving van {BedrijfsNaam}.");

            //systeemDeploymentView.EnableAutomaticLayout();
            systeemDeploymentView.Environment = Productie;
            systeemDeploymentView.Add(productieOmgeving);
            systeemDeploymentView.Add(customerComputer);
            systeemDeploymentView.Add(dataReplicationRelationship);

            // Set Styling
            Styles styles = views.Configuration.Styles;

            styles.Add(new ElementStyle(Tags.SoftwareSystem)
            {
                Background = "#1168bd", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(Tags.Container)
            {
                Background = "#438dd5", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(Tags.Component)
            {
                Background = "#85bbf0", Color = "#000000"
            });
            styles.Add(new ElementStyle(Tags.Person)
            {
                Background = "#08427b", Color = "#ffffff", Shape = Shape.Person
            });
            styles.Add(new ElementStyle(InternalSystemTag)
            {
                Background = "#999999", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(ExternalSystemTag)
            {
                Background = "#999999", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(WebBrowserTag)
            {
                Shape = Shape.WebBrowser
            });
            styles.Add(new ElementStyle(DatabaseTag)
            {
                Shape = Shape.Cylinder
            });
            styles.Add(new ElementStyle(FailoverTag)
            {
                Opacity = 25
            });
            styles.Add(new RelationshipStyle(FailoverTag)
            {
                Opacity = 25, Position = 70
            });
        }
Example #8
0
        private static void AddDocumentationDiagram(Workspace workspace, StructurizrDocumentationTemplate template)
        {
            Model model = workspace.Model;

            SoftwareSystem documentationProjectSoftwareSystem = model.AddSoftwareSystem(
                Location.Internal,
                "Documentation Project",
                "Visual Studio Project (or VS Code Workspace) containing all documentation artifacts");

            Container diagramsDefinitionsContainer = documentationProjectSoftwareSystem.AddContainer("Diagram Definitions",
                                                                                                     "This is core Structurizr Library functionality - architecture diagrams defined as a code",
                                                                                                     "C# code");

            Container documentationSectionsContainer = documentationProjectSoftwareSystem.AddContainer("Documentation Sections",
                                                                                                       "Documentation sections in Markdown format - these can reference screenshots and diagrams",
                                                                                                       "Markdown");

            Container screenshotsContainer = documentationProjectSoftwareSystem.AddContainer("Screenshots",
                                                                                             "Screenshots and other images that we want to include in the documentation",
                                                                                             "PNG");

            SoftwareSystem gitHubRepositorySoftwareSystem = model.AddSoftwareSystem(
                Location.Unspecified,
                "GitHub Repository",
                "Used as remote repository; we use it as online host for screenshots");

            Container onlineScreenshotsContainer = gitHubRepositorySoftwareSystem.AddContainer("Online Screenshots", "Screenshots in GitHub available with public URL", "PNG, HTTP");

            SoftwareSystem structurizrWorkspaceSoftwareSystem = model.AddSoftwareSystem(
                Location.Unspecified,
                "Online Structurizr Workspace",
                "Transforms diagram definitions into interactive diagrams and also hosts diagrams as images; hosts online documentation");

            Container interactiveDiagramsContainer = structurizrWorkspaceSoftwareSystem.AddContainer("Interactive Diagrams", "User can modify diagram layout; there is additional functionality that helps getting architecture insights", "Structurizr SAAS");

            Container diagramsAsImagesContainer = structurizrWorkspaceSoftwareSystem.AddContainer("Diagram PNGs", "Interactive diagrams are automatically exported to PNG format and made available online", "PNG, HTTP");

            Container documentationAsHtmlContainer = structurizrWorkspaceSoftwareSystem.AddContainer("Documentation Online", "Markdown documents are automatically presented as online HTML", "HTTP, HTML");

            // what uses what
            documentationProjectSoftwareSystem.Uses(gitHubRepositorySoftwareSystem, "Uses it as a Git Remote");

            documentationSectionsContainer.Uses(onlineScreenshotsContainer, "Markdown documents reference online screenshots on GitHub");

            documentationProjectSoftwareSystem.Uses(structurizrWorkspaceSoftwareSystem, "Pushes diagram definitions and documentation sections into Structurizr workspace");

            documentationAsHtmlContainer.Uses(diagramsAsImagesContainer, "Generated HTML references diagrams as images (replacement for customer references to interactive diagrams)");

            documentationAsHtmlContainer.Uses(onlineScreenshotsContainer, "Generated HTML references online screenshots on GitHub");

            interactiveDiagramsContainer.Uses(diagramsAsImagesContainer, "Are transformed to images automatically");

            diagramsDefinitionsContainer.Uses(interactiveDiagramsContainer, "Code is transformed to interactive diagrams");

            documentationSectionsContainer.Uses(documentationAsHtmlContainer, "Markdown documents are presented as HTML on Structurizr");

            documentationSectionsContainer.Uses(diagramsAsImagesContainer, "Markdown documents reference diagrams hosted on Structurizr");

            // diagrams
            ViewSet views = workspace.Views;

            SystemContextView documentationSystemContextView = views.CreateSystemContextView(
                documentationProjectSoftwareSystem,
                "DocumentationSystemContext",
                "Documentation System Context diagram.");

            documentationSystemContextView.AddNearestNeighbours(documentationProjectSoftwareSystem);

            ContainerView documentationContainerView = views.CreateContainerView(documentationProjectSoftwareSystem, "DocumentationContainerDiagram", "Documentation container diagram");

            documentationContainerView.AddAllContainers();

            foreach (var githubContainer in gitHubRepositorySoftwareSystem.Containers)
            {
                githubContainer.AddTags("GitHub Container");
                documentationContainerView.Add(githubContainer);
            }

            foreach (var structurizrContainer in structurizrWorkspaceSoftwareSystem.Containers)
            {
                structurizrContainer.AddTags("Structurizr Container");
                documentationContainerView.Add(structurizrContainer);
            }

            // styles
            Styles styles = views.Configuration.Styles;

            styles.Add(new ElementStyle("GitHub Container")
            {
                Background = "#00BFFF"
            });
            styles.Add(new ElementStyle("Structurizr Container")
            {
                Background = "#ADFF2F"
            });

            // documentation sections
            var documentationFolderPath = Path.Combine(AppContext.BaseDirectory, "Documentation");

            template.AddSection(documentationProjectSoftwareSystem, "Documentation system", 1,
                                new FileInfo(Path.Combine(documentationFolderPath, "DocumentationOfDocumentation.md")));
        }
Example #9
0
        static void Main(string[] args)
        {
            // a Structurizr workspace is the wrapper for a software architecture model, views and documentation
            Workspace workspace = new Workspace("Supply Chain Planning", "Model of software systems used by Supply Chain Planning.");

            #region Model

            Model model = workspace.Model;

            #region Users

            Person scpUser      = model.AddPerson(Location.Internal, "SCP User", "Modeller, Data Analyst or other users.");
            Person adminUser    = model.AddPerson(Location.Internal, "Administrator", "SCP Administrators.");
            Person externalUser = model.AddPerson(Location.External, "External User", "Other users outside of SCP");

            #endregion

            #region Software systems

            SoftwareSystem amsSoftwareSystem = model.AddSoftwareSystem(
                Location.Internal,
                "AMS",
                "Assumption Management System\n\nStores and allows user to manage model versions and model inputs (assumptions)");

            SoftwareSystem runsControllerSoftwareSystem = model.AddSoftwareSystem(
                Location.Internal,
                "Runs Controller",
                "Executes model submissions and post-processing tasks and allows user to monitor and manage submissions");

            SoftwareSystem modelOutputsStorageSoftwareSystem = model.AddSoftwareSystem(
                Location.Internal,
                "Model Outputs Storage",
                "Databases and shared file system that stores outputs of model runs");

            SoftwareSystem hangfireSoftwareSystem = model.AddSoftwareSystem(
                Location.Internal,
                "Hangfire",
                "Recurring and background jobs processing\n\n" +
                "Executes long-running background tasks (like submission creation in Runs Controller) " +
                "and recurring tasks (like model outputs registration and retention policy)");

            SoftwareSystem analyticalDataStoreSoftwareSystem = model.AddSoftwareSystem(
                Location.Internal,
                "Analytical Data Store",
                "This includes all databases and other data stores that can be used as data sources for Spotfire or AMS");

            SoftwareSystem spotfireSoftwareSystem = model.AddSoftwareSystem(
                Location.Internal,
                "Spotfire",
                "TIBCO Spotfire dashboards visualize data (model outputs and other available data)");

            SoftwareSystem externalDataSourcesSoftwareSystem = model.AddSoftwareSystem(
                Location.External,
                "External Data Source",
                "All other source of data external to SCP from which import data");

            SoftwareSystem controlFrameworkSoftwareSystem = model.AddSoftwareSystem(
                Location.Internal,
                "Control Framework",
                "Collection of configurable SSIS packages running as SQL jobs perfroming data-centric background and reccuring tasks");

            SoftwareSystem p2cModelDevelopmentSoftwareSystem = model.AddSoftwareSystem(
                Location.Internal,
                "P2C Model Development",
                "Toolset for development and testing of P2C model");

            #endregion

            #region Containers

            #region AMS Containers

            var amsLightswitchWebApplicationContainer = amsSoftwareSystem.AddContainer("LightSwitch Web Application",
                                                                                       "Main navigation, browse and edit screens, shell for some custom JavaScript controls",
                                                                                       "LightSwitch HTML Client (SPA), Knockout JS");

            var amsAspNetMvcWebApplicationContainer = amsSoftwareSystem.AddContainer("MVC Web Application",
                                                                                     "Dashboard, Type system versions, State Validation, Key Inputs, State Merging, Submission Progress",
                                                                                     "ASP.NET MVC, Kendo UI, Knockout JS");

            var amsApiApplicationContainer = amsSoftwareSystem.AddContainer("AMS API Application", "AMS back-end", "ASP.NET Web API, Entity Framework, LightSwitch Server");

            var amsDatabaseContainer = amsSoftwareSystem.AddContainer("AMS Database", "Stores project hierarchy, assumptions, type system definition and other data managed by AMS", "MS SQL Server 2016");

            var amsCacheContainer = amsSoftwareSystem.AddContainer("AMS Distributed Cache", "In-memory cache for frequently accessed and hard-to-read data; also used for messaging between Hangfire and AMS", "Redis, Windows Service");

            #endregion

            #region Hangfire Containers

            var hangfireDashboardContainer = hangfireSoftwareSystem.AddContainer("Hangfire Dashboard", "User interface for Hangfire monitoring and management", "Web Application");

            var hangfireServiceContainer = hangfireSoftwareSystem.AddContainer("Hangfire Windows Service", "Executes background tasks and recurrent jobs", ".Net Framework Windows Application, Shares code base with AMS API Application");

            var hangfireDatabaseContainer = hangfireSoftwareSystem.AddContainer("Hangfire Database", "Stores hangfire jobs, results and other Hangfire data", "MS SQL Server 2016");

            var hangfireMessageQueuesContainer = hangfireSoftwareSystem.AddContainer("Message Queues", "Queues for jobs to be executed by Hangfire", "Microsoft Message Queues");

            #endregion

            #region Control Framework Containers

            var controlFrameworkDatabaseContainer = controlFrameworkSoftwareSystem.AddContainer("ControlFrameworkDB", "Control Framework database", "MS SQL Server 2016 database");
            //var controlFrameworkJobs =

            #endregion

            #region Runs Controller Containers

            var rcDistributorContainer = runsControllerSoftwareSystem.AddContainer("Runs Controller Distributor",
                                                                                   "Maintains package queue; distributes packages to clients; implements APIs for submission creation and portal",
                                                                                   ".Net, C#, Windows Service");

            var rcClientContainer = runsControllerSoftwareSystem.AddContainer("Runs Controller Client", "Executes packages", ".Net, C#, Windows Service");

            var rcDatabaseContainer = runsControllerSoftwareSystem.AddContainer("Runs Controller Database", "Stores Runs Controller data", "SQL Server 2016 database");

            var rcReportingAPIServiceContainer = runsControllerSoftwareSystem.AddContainer("RunsController Reporting API Service", "Provides APIs for reporting on Runs Controller data", "ASP.NET Core, Windows Service");

            var rcCommandLineToolContainer = runsControllerSoftwareSystem.AddContainer("Runs Controller Command Line Tool",
                                                                                       "Command Line interface to Runs Controller Distributor; allows for creation of Arena packages",
                                                                                       ".Net, C#, console application");

            var rcSubmissionToolContainer = runsControllerSoftwareSystem.AddContainer("Runs Controller Submission Tool",
                                                                                      "The tools for creation of Arena submissions",
                                                                                      "C# Windows Forms application, ClickOnce deployment");

            var rcNotificationClientContainer = runsControllerSoftwareSystem.AddContainer("Runs Controller Notification Client",
                                                                                          "Monitors user's submissions and displays notification when submission is finished",
                                                                                          "C# Windows Forms application");

            var rcPortalContainer = runsControllerSoftwareSystem.AddContainer("Runs Controller Portal", "Runs Controller user interface", "ASP.NET MVC web application");

            #endregion

            #region Analytical Data Store Containers

            var adsDatabaseContainer = analyticalDataStoreSoftwareSystem.AddContainer("AnalyticalDataStore", "ADS database", "MS SQL Server 2016 database");
            var actualsTimeSeriesDatabaseContainer = analyticalDataStoreSoftwareSystem.AddContainer("Actuals_TimeSeries", "Actuals Time Series database", "MS SQL Server 2016 database");
            var projectDatabaseContainer           = analyticalDataStoreSoftwareSystem.AddContainer("Project", "Project database", "MS SQL Server 2016 database");
            var sckbDatabaseContainer          = analyticalDataStoreSoftwareSystem.AddContainer("SCKBDatabase", "SCKB database", "MS SQL Server 2016 database");
            var sckbReportingDatabaseContainer = analyticalDataStoreSoftwareSystem.AddContainer("SCKBReportingDB", "SCKB Reporting database", "MS SQL Server 2016 database");

            #endregion

            #region Model Outputs Storage Containers

            var modelOutputsFileSharesContainer         = modelOutputsStorageSoftwareSystem.AddContainer("Model Outputs File Shares", "Store model output files and post-processed data", "File Share");
            var modelOutputsKpiDatabaseContainer        = modelOutputsStorageSoftwareSystem.AddContainer("ModelOutputs_KPI", "Model Outputs KPI database", "MS SQL Server 2016 database");
            var modelOutputsTimeSeriesDatabaseContainer = modelOutputsStorageSoftwareSystem.AddContainer("ModelOutputs_TimeSeries", "Model Outputs Time Series database", "MS SQL Server 2016 database");
            var modelOutputsProcessDatabaseContainer    = modelOutputsStorageSoftwareSystem.AddContainer("ModelOutputsProcess", "Model Outputs Process database", "MS SQL Server 2016 database");

            #endregion

            #region Deployment Nodes

            var amsWebServer = model.AddDeploymentNode("IORPER-WEB01", "AMS Web Server", "Windows Server 2012 R2");

            amsWebServer.Add(hangfireServiceContainer);
            amsWebServer.Add(hangfireMessageQueuesContainer);
            amsWebServer.Add(amsCacheContainer);

            var amsIis = amsWebServer.AddDeploymentNode("IIS", "Internet Information Services", "IIS 8.5");
            amsIis.Add(amsApiApplicationContainer);
            amsIis.Add(amsLightswitchWebApplicationContainer);
            amsIis.Add(amsAspNetMvcWebApplicationContainer);
            amsIis.Add(hangfireDashboardContainer);

            var clusterNode1        = model.AddDeploymentNode("IORPER-C02SQ01", "Node 1 of the failover cluster", "Windows Server 2012 R2");
            var node1databaseServer = clusterNode1.AddDeploymentNode("SQ2014SCAP01", "Database Server for Analytical Data Store", "SQL Server 2016");
            node1databaseServer.Add(adsDatabaseContainer);
            node1databaseServer.Add(controlFrameworkDatabaseContainer);
            node1databaseServer.Add(actualsTimeSeriesDatabaseContainer);
            node1databaseServer.Add(modelOutputsKpiDatabaseContainer);
            node1databaseServer.Add(modelOutputsTimeSeriesDatabaseContainer);
            node1databaseServer.Add(modelOutputsProcessDatabaseContainer);
            node1databaseServer.Add(projectDatabaseContainer);
            node1databaseServer.Add(sckbDatabaseContainer);
            node1databaseServer.Add(sckbReportingDatabaseContainer);

            var clusterNode2 = model.AddDeploymentNode("IORPER-C02SQ02", "Node 2 of the failover cluster", "Windows Server 2012 R2");

            var node2databaseServer = clusterNode2.AddDeploymentNode("SQ2014SCAP02", "Database Server for operational databases", "SQL Server 2016");

            var amsDatabase = node2databaseServer.AddDeploymentNode("AMS", "AMS database - the dbo schema contains AMS tables and vies, hangfire schema contains Hangfire tables", "SQL Server Database");
            amsDatabase.Add(amsDatabaseContainer);
            amsDatabase.Add(hangfireDatabaseContainer);

            var runsControllerDistributorServer = model.AddDeploymentNode("IOPL-S0044", "Runs Controller Distributor Server (alias UnityServer)", "Windows Server 2008 R2");
            runsControllerDistributorServer.Add(rcDistributorContainer);

            node2databaseServer.Add(rcDatabaseContainer);

            var gen8processingClients     = model.AddDeploymentNode("Gen8 Runs Controller clients servers (Arena and AnyLogic)", "Gen8 Runs Controller client servers (16 processing slots)", "Windows Server 2012 R2", 31);
            var gen8postProcessingClients = model.AddDeploymentNode("Gen8 Runs Controller clients server (post-processing)", "Gen8 Runs Controller client servers (1 processing slot)", "Windows Server 2012 R2", 1);

            var gen9processingClients     = model.AddDeploymentNode("Gen9 Runs Controller clients servers (Arena and AnyLogic)", "Gen8 Runs Controller client servers (24 processing slots)", "Windows Server 2012 R2", 24);
            var gen9postProcessingClients = model.AddDeploymentNode("Gen9 Runs Controller clients server (post-processing)", "Gen8 Runs Controller client servers (2 processing slot)", "Windows Server 2012 R2", 2);

            gen8processingClients.Add(rcClientContainer);
            gen8postProcessingClients.Add(rcClientContainer);
            gen9processingClients.Add(rcClientContainer);
            gen9postProcessingClients.Add(rcClientContainer);

            #endregion

            #endregion

            #region Relationships (what uses what)

            scpUser.Uses(amsSoftwareSystem, "Manages model versions, model inputs and creates submissions");

            scpUser.Uses(amsLightswitchWebApplicationContainer, "Manages model versions, model inputs and creates submissions");
            scpUser.Uses(amsAspNetMvcWebApplicationContainer, "Uses specialized AMS screens");

            scpUser.Uses(runsControllerSoftwareSystem, "Monitors and manages submissions");
            scpUser.Uses(spotfireSoftwareSystem, "Uses dashboards to visualize and analyze data");

            adminUser.Uses(amsSoftwareSystem, "Manages system settings and other protected data");

            adminUser.Uses(amsLightswitchWebApplicationContainer, "Manages system settings and other protected data");

            adminUser.Uses(runsControllerSoftwareSystem, "Manages Runs Controller setting (e.g. which clients are active)");
            adminUser.Uses(hangfireSoftwareSystem, "Manages Hangfire settings; can restart failed jobs etc.");
            adminUser.Uses(hangfireDashboardContainer, "Manages Hangfire settings; can restart failed jobs etc.");

            externalUser.Uses(spotfireSoftwareSystem, "Uses public dashboards or outputs produced by project teams using Spotfire");

            amsSoftwareSystem.Uses(runsControllerSoftwareSystem, "Fetches submission status");
            amsSoftwareSystem.Uses(hangfireSoftwareSystem, "Triggers submission creation in Runs Controller");
            amsSoftwareSystem.Uses(analyticalDataStoreSoftwareSystem, "Imports data from analytical data store that are used as model inputs (e.g. actual supply chain data)");
            amsSoftwareSystem.Uses(controlFrameworkSoftwareSystem, "Provides user interface for Control Framework configuration; references Control Framework messages as model inputs");

            controlFrameworkSoftwareSystem.Uses(analyticalDataStoreSoftwareSystem, "Imports (into) and transforms data");
            controlFrameworkSoftwareSystem.Uses(externalDataSourcesSoftwareSystem, "Imports data (from)");
            controlFrameworkSoftwareSystem.Uses(modelOutputsStorageSoftwareSystem, "Loads data to models outputs databases");

            runsControllerSoftwareSystem.Uses(modelOutputsStorageSoftwareSystem, "Generates model outputs");

            hangfireSoftwareSystem.Uses(modelOutputsStorageSoftwareSystem, "Registers created model outputs, applies retention policy");
            hangfireSoftwareSystem.Uses(runsControllerSoftwareSystem, "Creates model submissions and post-processing submissions");

            analyticalDataStoreSoftwareSystem.Uses(amsSoftwareSystem, "Has read-only access to AMS data (project hierarchy, object model, reference data and objects)");
            analyticalDataStoreSoftwareSystem.Uses(externalDataSourcesSoftwareSystem, "Imports data from external systems.");

            spotfireSoftwareSystem.Uses(modelOutputsStorageSoftwareSystem, "Visualizes model outputs");
            spotfireSoftwareSystem.Uses(analyticalDataStoreSoftwareSystem, "Visualizes other available data");
            spotfireSoftwareSystem.Uses(runsControllerSoftwareSystem, "Reads submission details for environment performance dashboard");

            p2cModelDevelopmentSoftwareSystem.Uses(amsSoftwareSystem, "Exports model versions");

            amsLightswitchWebApplicationContainer.Uses(amsApiApplicationContainer, "Uses", "JSON/HTTP");
            amsAspNetMvcWebApplicationContainer.Uses(amsApiApplicationContainer, "Uses", "JSON/HTTP");

            amsApiApplicationContainer.Uses(amsDatabaseContainer, "Reads from and writes to", "ADO.Net");

            amsApiApplicationContainer.Uses(amsCacheContainer, "Reads from, writes to and invalidates data in", "StackExchange.Redis client");
            amsApiApplicationContainer.Uses(amsCacheContainer, "Subscribes to notifications from Hangfire", "Redis Pub/Sub");

            hangfireServiceContainer.Uses(hangfireMessageQueuesContainer, "Processes queued jobs");
            hangfireServiceContainer.Uses(hangfireDatabaseContainer, "Persists jobs data");
            hangfireServiceContainer.Uses(amsCacheContainer, "Reads from, writes to and invalidates in", "StackExchange.Redis client");
            hangfireServiceContainer.Uses(amsCacheContainer, "Publishes notifications for AMS", "Redis Pub/Sub");
            hangfireServiceContainer.Uses(amsDatabaseContainer, "Reads from and writes to", "ADO.Net");
            hangfireServiceContainer.Uses(modelOutputsFileSharesContainer, "Registers created model output files");
            hangfireServiceContainer.Uses(modelOutputsFileSharesContainer, "Removes old model output files");
            hangfireServiceContainer.Uses(modelOutputsKpiDatabaseContainer, "Removes old model outputs");
            hangfireServiceContainer.Uses(modelOutputsTimeSeriesDatabaseContainer, "Removes old model outputs");

            hangfireDashboardContainer.Uses(hangfireServiceContainer, "Provides user interface for");

            amsApiApplicationContainer.Uses(hangfireMessageQueuesContainer, "Enqueues and schedules jobs using");

            var failoverRelationship        = clusterNode2.Uses(clusterNode1, "Failover to", "Windows Server Failover Cluster");
            var failoverRelationshipReverse = clusterNode1.Uses(clusterNode2, "Failover to", "Windows Server Failover Cluster");

            rcDistributorContainer.Uses(rcDatabaseContainer, "Reads from and writes to", "ADO.Net");
            rcClientContainer.Uses(rcDistributorContainer, "Requests packages to execute; send package reports and changes in package status", "WCF, http");
            rcPortalContainer.Uses(rcDistributorContainer, "Reads data to display from and sends requests to manage data to", "WCF, http");
            scpUser.Uses(rcPortalContainer, "Manages submissions and packages");

            hangfireServiceContainer.Uses(rcDistributorContainer, "Creates AnyLogic packages and submissions, creates post-processing packages and submissions", "WCF, http");
            hangfireServiceContainer.Uses(rcReportingAPIServiceContainer, "Reads submission details to be cached in AMS and displayed in AMS", "http");

            spotfireSoftwareSystem.Uses(rcReportingAPIServiceContainer, "Reads submission details to be displayed on the environment performance dashboard", "http");

            amsApiApplicationContainer.Uses(rcDistributorContainer, "Updates Customer and Project details", "WCF, http");

            rcCommandLineToolContainer.Uses(rcDistributorContainer, "Creates Arena packages and submissions, updates customer and project", "WCF, http");

            rcSubmissionToolContainer.Uses(rcCommandLineToolContainer, "Uses it to creates Arena packages and submissions an to update customer and project");

            rcNotificationClientContainer.Uses(rcDistributorContainer, "Subscribes to user's submission changes", "WCF, http");

            rcReportingAPIServiceContainer.Uses(rcDatabaseContainer, "Reads persisted submission data", "ADO.Net");
            rcReportingAPIServiceContainer.Uses(rcDistributorContainer, "Reads queue details", "WCF, http");

            scpUser.Uses(rcNotificationClientContainer, "Gets notified when his submission is finished");
            scpUser.Uses(rcSubmissionToolContainer, "Creates Arena submissions using");

            rcClientContainer.Uses(modelOutputsFileSharesContainer, "Generates output files in");

            p2cModelDevelopmentSoftwareSystem.Uses(amsApiApplicationContainer, "Exports model versions to");

            #endregion

            #endregion

            #region Views (diagrams)

            // define some views (the diagrams you would like to see)
            ViewSet views = workspace.Views;

            #region Enterprise context

            EnterpriseContextView enterpriseContextView = views.CreateEnterpriseContextView("EnterpriseContext", "Enterprise Context diagram.");

            enterpriseContextView.PaperSize = PaperSize.A4_Landscape;
            enterpriseContextView.AddAllSoftwareSystems();
            enterpriseContextView.AddAllPeople();

            #endregion

            #region AMS System Context

            SystemContextView amsSystemContextView = views.CreateSystemContextView(
                amsSoftwareSystem,
                "AMSSystemContext",
                "AMS System Context diagram.");
            amsSystemContextView.AddNearestNeighbours(amsSoftwareSystem);
            amsSystemContextView.AddNearestNeighbours(hangfireSoftwareSystem);

            #endregion

            #region Runs Controller System Context

            SystemContextView runsControllerSystemContextView = views.CreateSystemContextView(
                runsControllerSoftwareSystem,
                "RunsControllerSystemContext",
                "RunsController System Context diagram.");
            runsControllerSystemContextView.AddNearestNeighbours(runsControllerSoftwareSystem);

            #endregion

            #region AMS Container Diagram

            var amsContainerView = views.CreateContainerView(amsSoftwareSystem, "AMSContainerDiagram", "AMS container diagram");
            amsContainerView.AddAllContainers();

            amsContainerView.Add(scpUser);
            amsContainerView.Add(adminUser);

            amsContainerView.Add(hangfireServiceContainer);
            amsContainerView.Add(hangfireMessageQueuesContainer);
            amsContainerView.Add(hangfireServiceContainer);
            amsContainerView.Add(p2cModelDevelopmentSoftwareSystem);

            #endregion

            #region Runs Controller Container Diagram

            var runsControllerContainerView = views.CreateContainerView(runsControllerSoftwareSystem, "RCContainerDiagram", "Runs Controller container diagram");
            runsControllerContainerView.AddAllContainers();
            runsControllerContainerView.Add(scpUser);

            runsControllerContainerView.Add(hangfireServiceContainer);
            runsControllerContainerView.Add(amsApiApplicationContainer);
            runsControllerContainerView.Add(spotfireSoftwareSystem);
            runsControllerContainerView.Add(modelOutputsFileSharesContainer);

            #endregion

            #region Hangfire Container Diagram

            var hangfireContainerView = views.CreateContainerView(hangfireSoftwareSystem, "HangfireContainerDiagram", "Hangfire container diagram");
            hangfireContainerView.AddAllContainers();

            hangfireContainerView.Add(adminUser);

            hangfireContainerView.Add(amsCacheContainer);
            hangfireContainerView.Add(amsDatabaseContainer);
            hangfireContainerView.Add(amsApiApplicationContainer);

            #endregion

            #region AMS Deployment Diagram

            var amsDeploymentView = views.CreateDeploymentView("AMSDeploymentDiagram", "AMS Deployment Diagram");

            amsDeploymentView.Add(amsWebServer);
            amsDeploymentView.Add(clusterNode2);
            amsDeploymentView.Add(clusterNode1);
            amsDeploymentView.Add(failoverRelationship);
            amsDeploymentView.Add(failoverRelationshipReverse);

            #endregion

            #region Runs Controller Deployment Diagram

            var runsControllerDeploymentView = views.CreateDeploymentView("RunsControllerDeploymentDiagram", "Runs Controller Deployment Diagram");

            runsControllerDeploymentView.Add(runsControllerDistributorServer);
            runsControllerDeploymentView.Add(gen8processingClients);
            runsControllerDeploymentView.Add(gen8postProcessingClients);
            runsControllerDeploymentView.Add(gen9processingClients);
            runsControllerDeploymentView.Add(gen9postProcessingClients);
            runsControllerDeploymentView.Add(clusterNode2);
            runsControllerDeploymentView.Add(clusterNode2);
            runsControllerDeploymentView.Add(clusterNode1);
            runsControllerDeploymentView.Add(failoverRelationship);
            runsControllerDeploymentView.Add(failoverRelationshipReverse);

            #endregion

            #region Submission creation workflow

            var submissionCreationWorkflow = views.CreateDynamicView("SubmissionWorkflow", "Submission creation workflow");

            submissionCreationWorkflow.Add(p2cModelDevelopmentSoftwareSystem, "Exports new model version to AMS", amsSoftwareSystem);
            submissionCreationWorkflow.Add(scpUser, "Defines project, scenario, case and input state", amsSoftwareSystem);
            submissionCreationWorkflow.Add(scpUser, "Initiates creation of a new submission", amsSoftwareSystem);
            submissionCreationWorkflow.Add(amsSoftwareSystem, "Creates Hangfire job to create submission in Runs Controller", hangfireSoftwareSystem);
            submissionCreationWorkflow.Add(hangfireSoftwareSystem, "Creates submission in Runs Controller", runsControllerSoftwareSystem);
            submissionCreationWorkflow.Add(amsSoftwareSystem, "Receives submission creation notification from Hangfire through Redis", hangfireSoftwareSystem);
            submissionCreationWorkflow.Add(scpUser, "Receives on-screen notification about created submission", amsSoftwareSystem);

            #endregion

            #region Submission execution and post-processing

            var submissionExecutionWorkflow = views.CreateDynamicView("SubmissionExecutionWorkflow", "Submission execution workflow");

            submissionExecutionWorkflow.Add(runsControllerSoftwareSystem, "Finished submission packages produce model outputs", modelOutputsStorageSoftwareSystem);
            submissionExecutionWorkflow.Add(hangfireSoftwareSystem, "Registers produced model outputs", modelOutputsStorageSoftwareSystem);
            submissionExecutionWorkflow.Add(hangfireSoftwareSystem, "Regularly checks submissions and creates post-processing submission", modelOutputsStorageSoftwareSystem);
            submissionExecutionWorkflow.Add(runsControllerSoftwareSystem, "Post-processing package produces post-processed model outputs", modelOutputsStorageSoftwareSystem);
            submissionExecutionWorkflow.Add(controlFrameworkSoftwareSystem, "Loads post-processed model outputs to database and archive", modelOutputsStorageSoftwareSystem);
            submissionExecutionWorkflow.Add(hangfireSoftwareSystem, "Performs post-load processing", modelOutputsStorageSoftwareSystem);
            submissionExecutionWorkflow.Add(spotfireSoftwareSystem, "Loaded post-processed outputs are available in Spotfire", modelOutputsStorageSoftwareSystem);

            #endregion

            #region Styles

            // add some styling
            Styles styles = views.Configuration.Styles;
            styles.Add(new ElementStyle(Tags.SoftwareSystem)
            {
                Background = "#1168bd", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(Tags.Person)
            {
                Background = "#08427b", Color = "#ffffff", Shape = Shape.Person
            });
            // styles.Add(new RelationshipStyle(Tags.Relationship) {Routing = Routing.Orthogonal, Position = 30 });

            #endregion

            #endregion

            #region Documentation

            // add some documentation
            StructurizrDocumentationTemplate template = new StructurizrDocumentationTemplate(workspace);

            var documentationFolderPath = Path.Combine(AppContext.BaseDirectory, "Documentation");

            template.AddContextSection(amsSoftwareSystem, new FileInfo(Path.Combine(documentationFolderPath, "Context.md")));
            template.AddFunctionalOverviewSection(amsSoftwareSystem, new FileInfo(Path.Combine(documentationFolderPath, "FunctionalOverview.md")));
            template.AddDataSection(amsSoftwareSystem, new FileInfo(Path.Combine(documentationFolderPath, "Data.md")));
            template.AddPrinciplesSection(amsSoftwareSystem, new FileInfo(Path.Combine(documentationFolderPath, "Principles.md")));
            template.AddSoftwareArchitectureSection(amsSoftwareSystem, new FileInfo(Path.Combine(documentationFolderPath, "SoftwareArchitecture.md")));
            template.AddDeploymentSection(amsSoftwareSystem, new FileInfo(Path.Combine(documentationFolderPath, "Deployment.md")));
            template.AddOperationAndSupportSection(amsSoftwareSystem, new FileInfo(Path.Combine(documentationFolderPath, "OperationAndSupport.md")));
            template.AddInfrastructureArchitectureSection(amsSoftwareSystem, new FileInfo(Path.Combine(documentationFolderPath, "InfrastructureArchitecture.md")));
            #endregion

            // documentation on documentation
            AddDocumentationDiagram(workspace, template);

            #region Upload; generate local DGML; generate local PlantUML

            // upload workspace to Structurizr (https://structurizr.com/)
            UploadWorkspaceToStructurizr(workspace);

            // Convert diagrams to DGML - dgml files can be opened using Visual Studio (extension is needed for VS 2017)
            var dgml = workspace.ToDgml();
            dgml.WriteToFile("c4model.dgml");

            // Convert diagrams to PlantUML format (http://plantuml.com/)
            StringWriter   stringWriter   = new StringWriter();
            PlantUMLWriter plantUMLWriter = new PlantUMLWriter();
            plantUMLWriter.Write(workspace, stringWriter);
            // content of the generated file can be visualized online (http://www.plantuml.com/plantuml/uml/)
            // or converted to image locally (using local PlantUML jar + Graphwiz or one of available VS Code extensions)
            File.WriteAllText("c4model_plant_UML.txt", stringWriter.ToString());

            #endregion
        }
Example #10
0
        static void Main(string[] args)
        {
            Workspace workspace = new Workspace("Park Soft", "Software for parking system");
            Model     model     = workspace.Model;
            ViewSet   views     = workspace.Views;

            AddContext(model, views);
            model.Enterprise = new Enterprise("System parkingowy");
            Person customer = model.AddPerson(
                Location.External,
                "Klient",
                "Klient parkingu, " +
                "posiada konto w systemie");

            Person parkingOperator = model.AddPerson(
                Location.External,
                "Operator",
                "Operator parkingu, " +
                "posiada konto w systemie");

            SoftwareSystem clientPlatformSystem = model.AddSoftwareSystem(
                Location.Internal,
                "Platforma kliencka",
                "Pozwala na zarządzanie swoimi rezerwacjami");

            customer.Uses(clientPlatformSystem, "Używa");

            SoftwareSystem mainframeParkingSystem = model.AddSoftwareSystem(
                Location.Internal,
                "System parkingowy",
                "Core'owy system parkingowy.");

            clientPlatformSystem.Uses(
                mainframeParkingSystem,
                "Pobiera informacje/Wysyła informacje");
            parkingOperator.Uses(mainframeParkingSystem, "obsługuje");

            SoftwareSystem emailSystem = model.AddSoftwareSystem(Location.Internal,
                                                                 "E-mail System", "System e-mailowy Microsoft Exchange");

            clientPlatformSystem.Uses(emailSystem, "Wysyła e-maile używając");
            emailSystem.Delivers(customer, "Wysyła e-maile do");
            clientPlatformSystem.Uses(
                mainframeParkingSystem,
                "Pobiera informacje/Wysyła informacje");



            SystemContextView systemContextView = views.CreateSystemContextView(
                clientPlatformSystem,
                "SystemContext",
                "Diagram kontekstowy systemu parkingowego");

            systemContextView.AddNearestNeighbours(clientPlatformSystem);
            systemContextView.AddAnimation(clientPlatformSystem);
            systemContextView.AddAnimation(customer);
            //systemContextView.AddAnimation(parkingOperator);
            systemContextView.AddAnimation(mainframeParkingSystem);

            //wcześniej zdefiniowany kontekst
            Container mobileApp = mainframeParkingSystem.AddContainer(
                "Aplikacja mobilna",
                "Dostarcza ograniczoną funkcjonalność bankowości online dla klienta",
                "Xamarin");
            Container apiApplication = mainframeParkingSystem.AddContainer(
                "API",
                "Dostarcza funkcjonalność bankowości online poprzez JSON/HTTP",
                "Java i Spring MVC");
            Container database = mainframeParkingSystem.AddContainer(
                "Baza danych", "Informacje o klientach, hashowane hasła, logi",
                "Relacyjna baza danych");

            parkingOperator.Uses(mobileApp, "Używa", "");
            apiApplication.Uses(database,
                                "Czyta/Zapisuje",
                                "JDBC");
            apiApplication.Uses(mainframeParkingSystem,
                                "Używa",
                                "XML/HTTPS");
            apiApplication.Uses(emailSystem, "Wysyła maile", "SMTP");


            ContainerView containerView = views.CreateContainerView(
                clientPlatformSystem,
                "Containers",
                "Diagram kontenerów systemu Platformy Bankowowości Online");

            containerView.Add(customer);
            containerView.AddAllContainers();
            containerView.Add(mainframeParkingSystem);
            containerView.Add(emailSystem);
            containerView.AddAnimation(
                customer,
                mainframeParkingSystem,
                emailSystem);
//            containerView.AddAnimation(mobileApp);
//            containerView.AddAnimation(apiApplication);


            UploadWorkspaceToStructurizr(workspace);
        }
Example #11
0
        static void Main(string[] args)
        {
            Workspace workspace = new Workspace("Architectural Kata: Make the Grade",
                                                "This is a model of the solution to the architectural kata \"Make the Grade\", found at http://nealford.com/katas/list.html.");

            #region Models

            Model model = workspace.Model;

            Person student = model.AddPerson("Student", "A student undertaking a test.");
            Person grader  = model.AddPerson("Grader", "A grader assessing the sudents' test answers.");
            Person admin   = model.AddPerson("Administrator", "A representative of the state authority in education.");

            SoftwareSystem resultsRepoSubSystem = model.AddSoftwareSystem("Results Repository", "Single location representing all of the test scores across the state.");
            admin.Uses(resultsRepoSubSystem, "Extracts grading reports.");

            SoftwareSystem testsCatalogueSubSystem = model.AddSoftwareSystem("Tests Catalogue", "Authoritative source for tests and grading rules.");
            admin.Uses(testsCatalogueSubSystem, "Administers tests.");

            SoftwareSystem localTestUnitSubSystem = model.AddSoftwareSystem("Local Testing Unit", "On-premises testing subsystem deployed in each testing center.");
            student.Uses(localTestUnitSubSystem, "Undertakes tests");
            grader.Uses(localTestUnitSubSystem, "Grades students");

            localTestUnitSubSystem.Uses(resultsRepoSubSystem, "Push results (batch)");
            localTestUnitSubSystem.Uses(testsCatalogueSubSystem, "Pull tests");

            Container resultsRepo = resultsRepoSubSystem.AddContainer("Results Database",
                                                                      "Single location representing all of the test scores across the state.", "Microsoft Azure SQL Database");
            resultsRepo.AddTags("Database");
            Container reportingService = resultsRepoSubSystem.AddContainer("Reporting Service",
                                                                           "A reporting system to know which students have taken the tests and what score they received.", "ASP.NET single page app");
            reportingService.Uses(resultsRepo, "Reads from");

            Container testsCatalogueService = testsCatalogueSubSystem.AddContainer("Catalogue Service",
                                                                                   "Web API provider of latest test and grading rules.", "ASP.NET Web API microservice");
            Container testsCatalogueFrontEnd = testsCatalogueSubSystem.AddContainer("Catalogue Front End",
                                                                                    "Front end application for administrators managing tests.", "ASP.NET MVC web app");
            Container testsRepo = testsCatalogueSubSystem.AddContainer("Tests Repository",
                                                                       "Stores test questions, answers and grading rules.", "NoSQL DBMS");
            testsRepo.AddTags("Database");
            testsCatalogueFrontEnd.Uses(testsRepo, "Reads from and writes to");
            testsCatalogueService.Uses(testsRepo, "Reads from");

            Container locatTestResultsStorage = localTestUnitSubSystem.AddContainer("Local Tests Storage",
                                                                                    "Stores test answers and grades for students from local testing unit.", "MySQL database");
            locatTestResultsStorage.AddTags("Database");
            Container testingApp = localTestUnitSubSystem.AddContainer("Testing application",
                                                                       "Allows students to undertake tests and graders to assess them.", "AngularJS web app");
            Container testResultQueue = localTestUnitSubSystem.AddContainer("Test results queue",
                                                                            "Asynchronous queue on which an event is placed when a student finishes a test, so that a grader can be notified.", "RabbitMQ");
            testResultQueue.AddTags("Queue");
            Container evaluator = localTestUnitSubSystem.AddContainer("Evaluator",
                                                                      "Retrieves a finished test, grades the multiple choice answers and gives manual control to graders", "");
            Container synchronizer = localTestUnitSubSystem.AddContainer("Synchronizer",
                                                                         "Uploads local test results to central repository", "WCF service");
            synchronizer.Uses(resultsRepoSubSystem, "Push results (batch)");
            synchronizer.Uses(locatTestResultsStorage, "Read from");

            testingApp.Uses(testResultQueue, "Undertake test");
            testingApp.Uses(testsCatalogueSubSystem, "Pull tests");
            testResultQueue.Uses(evaluator, "Notify grader");
            evaluator.Uses(locatTestResultsStorage, "Store and read results");
            evaluator.Uses(testsCatalogueSubSystem, "Pull tests");

            #endregion

            #region Views

            var layoutWorkspace = WorkspaceUtils.LoadWorkspaceFromJson(new FileInfo("layout.json"));

            ViewSet           viewSet     = workspace.Views;
            SystemContextView contextView = viewSet.CreateSystemContextView(testsCatalogueSubSystem, "SystemContext", "A system used for standardized testing across all public school systems grades 3-12.");
            contextView.AddAllSoftwareSystems();
            contextView.AddAllPeople();
            contextView.AddNearestNeighbours(testsCatalogueSubSystem);
            contextView.CopyLayoutInformationFrom(layoutWorkspace.Views.SystemContextViews.FirstOrDefault(x => x.Key == "SystemContext"));

            ContainerView resultsContainerView = viewSet.CreateContainerView(resultsRepoSubSystem, "ResultsContainer", "The container diagram for the Results Repository Subsystem.");
            admin.Uses(reportingService, "Extracts reports");
            resultsContainerView.Add(admin);
            resultsContainerView.AddAllContainers();
            resultsContainerView.CopyLayoutInformationFrom(layoutWorkspace.Views.ContainerViews.FirstOrDefault(x => x.Key == "ResultsContainer"));

            ContainerView testsContainerView = viewSet.CreateContainerView(testsCatalogueSubSystem, "TestsContainers", "The container diagram for the Tests Catalogue Subsystem.");
            admin.Uses(testsCatalogueFrontEnd, "Administers tests");
            testsContainerView.Add(admin);
            testsContainerView.AddAllContainers();
            testsContainerView.CopyLayoutInformationFrom(layoutWorkspace.Views.ContainerViews.FirstOrDefault(x => x.Key == "TestsContainers"));

            ContainerView testUnitContainerView = viewSet.CreateContainerView(localTestUnitSubSystem, "TestUnitsContainers", "The container diagram for the Local Testing Unit Subsystem.");
            student.Uses(testingApp, "Undertake test");
            grader.Uses(evaluator, "Grade test answers");
            testUnitContainerView.Add(student);
            testUnitContainerView.Add(grader);
            testUnitContainerView.AddAllContainers();
            testUnitContainerView.Add(resultsRepoSubSystem);
            testUnitContainerView.Add(testsCatalogueSubSystem);
            testUnitContainerView.CopyLayoutInformationFrom(layoutWorkspace.Views.ContainerViews.FirstOrDefault(x => x.Key == "TestUnitsContainers"));

            Styles styles = viewSet.Configuration.Styles;
            styles.Add(new ElementStyle(Tags.SoftwareSystem)
            {
                Background = "#1168bd", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(Tags.Person)
            {
                Background = "#08427b", Color = "#ffffff", Shape = Shape.Person
            });
            styles.Add(new ElementStyle("Database")
            {
                Shape = Shape.Cylinder
            });
            styles.Add(new ElementStyle("Queue")
            {
                Shape = Shape.Ellipse
            });

            #endregion

            PushWorkspace(workspace);
        }