diff --git a/404.html b/404.html index 6f2000f..b9513e6 100644 --- a/404.html +++ b/404.html @@ -4,7 +4,7 @@ Page Not Found | Porto SAP - + diff --git a/assets/js/377ca38f.1aeb167f.js b/assets/js/377ca38f.d1335c14.js similarity index 99% rename from assets/js/377ca38f.1aeb167f.js rename to assets/js/377ca38f.d1335c14.js index 90e3df0..d3f21c1 100644 --- a/assets/js/377ca38f.1aeb167f.js +++ b/assets/js/377ca38f.d1335c14.js @@ -1 +1 @@ -"use strict";(self.webpackChunkporto=self.webpackChunkporto||[]).push([[661],{3048:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>c});var i=t(4848),s=t(8453);const o={sidebar_position:1},r="Introduction",a={id:"Intro",title:"Introduction",description:'The terms "MUST," "MUST NOT," "REQUIRED," "SHALL," "SHALL NOT," "SHOULD," "SHOULD NOT," "RECOMMENDED," "MAY," and "OPTIONAL" in this document are defined as per RFC 2119.',source:"@site/docs/Intro.md",sourceDirName:".",slug:"/Intro",permalink:"/Porto/docs/Intro",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/Intro.md",tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",next:{title:"Layers",permalink:"/Porto/docs/category/layers"}},l={},c=[{value:"Overview",id:"overview",level:2},{value:"Foundation",id:"foundation",level:2},{value:"Benefits",id:"benefits",level:2},{value:"Suitability",id:"suitability",level:2},{value:"Concepts",id:"concepts",level:2}];function d(e){const n={a:"a",blockquote:"blockquote",h1:"h1",h2:"h2",img:"img",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsxs)(n.p,{children:['The terms "MUST," "MUST NOT," "REQUIRED," "SHALL," "SHALL NOT," "SHOULD," "SHOULD NOT," "RECOMMENDED," "MAY," and "OPTIONAL" in this document are defined as per ',(0,i.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc2119",children:"RFC 2119"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Porto"})," is a modern software architectural pattern providing a robust framework of guidelines, principles, and patterns. It is designed to facilitate the creation of software that is scalable, maintainable, and reusable. Porto allows you to start with a clean monolith and expand to microservices as needed, thanks to its modular structure which facilitates easy scaling and separation of concerns. Its adherence to the single responsibility principle enhances its integration with AI tools like GitHub Copilot, aiding in feature development, debugging, and more."]}),"\n",(0,i.jsx)("img",{src:"/Porto/img/porto_ship_2.png",alt:"Porto Components",style:{width:"100%"}}),"\n",(0,i.jsx)(n.h2,{id:"foundation",children:"Foundation"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Porto"})," is grounded in established architectural concepts such as ",(0,i.jsx)(n.strong,{children:"Domain Driven Design"})," (DDD), ",(0,i.jsx)(n.strong,{children:"Modular"}),", ",(0,i.jsx)(n.strong,{children:"Micro Kernel"}),", ",(0,i.jsx)(n.strong,{children:"Model View Controller"})," (MVC), ",(0,i.jsx)(n.strong,{children:"Layered"}),", and ",(0,i.jsx)(n.strong,{children:"Action Domain Responder"})," (ADR). It supports principles including ",(0,i.jsx)(n.strong,{children:"SOLID"}),", ",(0,i.jsx)(n.strong,{children:"OOP"}),", ",(0,i.jsx)(n.strong,{children:"LIFT"}),", ",(0,i.jsx)(n.strong,{children:"DRY"}),", ",(0,i.jsx)(n.strong,{children:"CoC"}),", ",(0,i.jsx)(n.strong,{children:"GRASP"}),", ",(0,i.jsx)(n.strong,{children:"Generalization"}),", ",(0,i.jsx)(n.strong,{children:"High Cohesion"}),", and ",(0,i.jsx)(n.strong,{children:"Low Coupling"}),". These principles ensure that systems built with Porto are not only maintainable and scalable but also straightforward and comprehensible."]}),"\n",(0,i.jsx)(n.h2,{id:"benefits",children:"Benefits"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Porto"}),"'s architectural pattern is strategically designed to facilitate scalability, enabling applications to efficiently adapt and grow with increasing demands. The pattern supports reusability, allowing components to be leveraged across multiple projects, which enhances development speed and consistency. Additionally, Porto prioritizes maintainability, providing clear guidelines that simplify system updates and upkeep, ensuring long-term performance and stability."]}),"\n",(0,i.jsx)(n.h2,{id:"suitability",children:"Suitability"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Porto"})," is particularly well-suited for medium to large-sized backend web applications. Its architectural principles support scalable development and effective management of diverse projects, enabling the reuse of business logic and features across multiple frameworks."]}),"\n",(0,i.jsx)(n.h2,{id:"concepts",children:"Concepts"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:"Porto"})," architecture consists primarily of ",(0,i.jsx)(n.strong,{children:"Layers"})," and ",(0,i.jsx)(n.strong,{children:"Components"}),"."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Layers"}),": The foundational divisions within Porto, specifically the ",(0,i.jsx)(n.strong,{children:"Containers"})," and ",(0,i.jsx)(n.strong,{children:"Ship"})," layers, dictate the structural organization of the code."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Components"}),": Defined as either ",(0,i.jsx)(n.strong,{children:"Main"})," or ",(0,i.jsx)(n.strong,{children:"Optional Components"}),", they outline the functionalities and responsibilities within the architecture. A detailed exploration of the components and their principles follows in subsequent sections."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Look at the images to understand how the layers are related: Containers are like cargo containers, relying on the Ship layer (the cargo ship), which, in turn, depends on the underlying Framework (the sea). When you open a container, you'll see well-organized boxes representing your components (AKA files or classes). Ultimately, your application's code floats atop a sea of code, from runtime environments to the operating system, down to the BIOS (deep ocean)."}),"\n",(0,i.jsx)("br",{}),"\n",(0,i.jsx)("br",{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{src:t(7100).A+"",width:"719",height:"347"})}),"\n",(0,i.jsx)("br",{}),"\n",(0,i.jsx)("br",{}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Note:"})," Initially an experimental solution for common backend development challenges, Porto has evolved into a widely adopted architecture, valued for its scalability and maintainability. Your feedback and contributions are always welcome."]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},7100:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/porto_container_1-585ffd377c62a2c4dc0258a489ecc63b.png"},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>a});var i=t(6540);const s={},o=i.createContext(s);function r(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunkporto=self.webpackChunkporto||[]).push([[661],{3048:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>c});var i=t(4848),s=t(8453);const o={sidebar_position:1},r="Introduction",a={id:"Intro",title:"Introduction",description:'The terms "MUST," "MUST NOT," "REQUIRED," "SHALL," "SHALL NOT," "SHOULD," "SHOULD NOT," "RECOMMENDED," "MAY," and "OPTIONAL" in this document are defined as per RFC 2119.',source:"@site/docs/Intro.md",sourceDirName:".",slug:"/Intro",permalink:"/Porto/docs/Intro",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/Intro.md",tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",next:{title:"Layers",permalink:"/Porto/docs/category/layers"}},l={},c=[{value:"Overview",id:"overview",level:2},{value:"Foundation",id:"foundation",level:2},{value:"Benefits",id:"benefits",level:2},{value:"Suitability",id:"suitability",level:2},{value:"Concepts",id:"concepts",level:2}];function d(e){const n={a:"a",blockquote:"blockquote",h1:"h1",h2:"h2",img:"img",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsxs)(n.p,{children:['The terms "MUST," "MUST NOT," "REQUIRED," "SHALL," "SHALL NOT," "SHOULD," "SHOULD NOT," "RECOMMENDED," "MAY," and "OPTIONAL" in this document are defined as per ',(0,i.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc2119",children:"RFC 2119"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Porto"})," is a modern software architectural pattern providing a robust framework of guidelines, principles, and patterns. It is designed to facilitate the creation of software that is scalable, maintainable, and reusable. Porto allows you to start with a clean monolith and expand to microservices as needed, thanks to its modular structure which facilitates easy scaling and separation of concerns. Its adherence to the single responsibility principle enhances its integration with AI tools like GitHub Copilot, aiding in feature development, debugging, and more."]}),"\n",(0,i.jsx)("img",{src:"/Porto/img/porto_ship_1.png",alt:"Porto Components",style:{width:"100%"}}),"\n",(0,i.jsx)(n.h2,{id:"foundation",children:"Foundation"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Porto"})," is grounded in established architectural concepts such as ",(0,i.jsx)(n.strong,{children:"Domain Driven Design"})," (DDD), ",(0,i.jsx)(n.strong,{children:"Modular"}),", ",(0,i.jsx)(n.strong,{children:"Micro Kernel"}),", ",(0,i.jsx)(n.strong,{children:"Model View Controller"})," (MVC), ",(0,i.jsx)(n.strong,{children:"Layered"}),", and ",(0,i.jsx)(n.strong,{children:"Action Domain Responder"})," (ADR). It supports principles including ",(0,i.jsx)(n.strong,{children:"SOLID"}),", ",(0,i.jsx)(n.strong,{children:"OOP"}),", ",(0,i.jsx)(n.strong,{children:"LIFT"}),", ",(0,i.jsx)(n.strong,{children:"DRY"}),", ",(0,i.jsx)(n.strong,{children:"CoC"}),", ",(0,i.jsx)(n.strong,{children:"GRASP"}),", ",(0,i.jsx)(n.strong,{children:"Generalization"}),", ",(0,i.jsx)(n.strong,{children:"High Cohesion"}),", and ",(0,i.jsx)(n.strong,{children:"Low Coupling"}),". These principles ensure that systems built with Porto are not only maintainable and scalable but also straightforward and comprehensible."]}),"\n",(0,i.jsx)(n.h2,{id:"benefits",children:"Benefits"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Porto"}),"'s architectural pattern is strategically designed to facilitate scalability, enabling applications to efficiently adapt and grow with increasing demands. The pattern supports reusability, allowing components to be leveraged across multiple projects, which enhances development speed and consistency. Additionally, Porto prioritizes maintainability, providing clear guidelines that simplify system updates and upkeep, ensuring long-term performance and stability."]}),"\n",(0,i.jsx)(n.h2,{id:"suitability",children:"Suitability"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Porto"})," is particularly well-suited for medium to large-sized backend web applications. Its architectural principles support scalable development and effective management of diverse projects, enabling the reuse of business logic and features across multiple frameworks."]}),"\n",(0,i.jsx)(n.h2,{id:"concepts",children:"Concepts"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:"Porto"})," architecture consists primarily of ",(0,i.jsx)(n.strong,{children:"Layers"})," and ",(0,i.jsx)(n.strong,{children:"Components"}),"."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Layers"}),": The foundational divisions within Porto, specifically the ",(0,i.jsx)(n.strong,{children:"Containers"})," and ",(0,i.jsx)(n.strong,{children:"Ship"})," layers, dictate the structural organization of the code."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Components"}),": Defined as either ",(0,i.jsx)(n.strong,{children:"Main"})," or ",(0,i.jsx)(n.strong,{children:"Optional Components"}),", they outline the functionalities and responsibilities within the architecture. A detailed exploration of the components and their principles follows in subsequent sections."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Look at the images to understand how the layers are related: Containers are like cargo containers, relying on the Ship layer (the cargo ship), which, in turn, depends on the underlying Framework (the sea). When you open a container, you'll see well-organized boxes representing your components (AKA files or classes). Ultimately, your application's code floats atop a sea of code, from runtime environments to the operating system, down to the BIOS (deep ocean)."}),"\n",(0,i.jsx)("br",{}),"\n",(0,i.jsx)("br",{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{src:t(7100).A+"",width:"719",height:"347"})}),"\n",(0,i.jsx)("br",{}),"\n",(0,i.jsx)("br",{}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Note:"})," Initially an experimental solution for common backend development challenges, Porto has evolved into a widely adopted architecture, valued for its scalability and maintainability. Your feedback and contributions are always welcome."]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},7100:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/porto_container_1-585ffd377c62a2c4dc0258a489ecc63b.png"},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>a});var i=t(6540);const s={},o=i.createContext(s);function r(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c7e95178.c0f2de20.js b/assets/js/c7e95178.c0f2de20.js new file mode 100644 index 0000000..afc28c2 --- /dev/null +++ b/assets/js/c7e95178.c0f2de20.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkporto=self.webpackChunkporto||[]).push([[884],{3610:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>l,contentTitle:()=>s,default:()=>u,frontMatter:()=>o,metadata:()=>r,toc:()=>d});var a=i(4848),n=i(8453);const o={sidebar_position:7},s="Quality Attributes",r={id:"Quality Attributes",title:"Quality Attributes",description:"Quality attributes are integral to Porto's design and implementation. They ensure the software meets the needs and expectations of its developers.",source:"@site/docs/Quality Attributes.md",sourceDirName:".",slug:"/Quality Attributes",permalink:"/Porto/docs/Quality Attributes",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/Quality Attributes.md",tags:[],version:"current",sidebarPosition:7,frontMatter:{sidebar_position:7},sidebar:"tutorialSidebar",previous:{title:"Monolithic to Microservices",permalink:"/Porto/docs/Features/Monolithic to MicroServices"},next:{title:"Implementations",permalink:"/Porto/docs/Implementations"}},l={},d=[{value:"Modularity & Reusability",id:"modularity--reusability",level:2},{value:"Maintainability & Scalability",id:"maintainability--scalability",level:2},{value:"Testability & Debuggability",id:"testability--debuggability",level:2},{value:"Adaptability & Evolvability",id:"adaptability--evolvability",level:2},{value:"Usability & Learnability",id:"usability--learnability",level:2},{value:"Extensibility & Flexibility",id:"extensibility--flexibility",level:2},{value:"Agility & Upgradability",id:"agility--upgradability",level:2}];function c(e){const t={code:"code",em:"em",h1:"h1",h2:"h2",p:"p",...(0,n.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.h1,{id:"quality-attributes",children:"Quality Attributes"}),"\n",(0,a.jsx)(t.p,{children:"Quality attributes are integral to Porto's design and implementation. They ensure the software meets the needs and expectations of its developers."}),"\n",(0,a.jsx)(t.h2,{id:"modularity--reusability",children:"Modularity & Reusability"}),"\n",(0,a.jsxs)(t.p,{children:["In Porto, your application business logic lives in Containers. Porto Containers are similar in nature to the Modules ",(0,a.jsx)(t.em,{children:"(from the Modular architecture)"})," and Domains ",(0,a.jsx)(t.em,{children:"(from the DDD architecture)"}),"."]}),"\n",(0,a.jsx)(t.p,{children:"Containers can depend on other Containers, similar to how a layer can depend on other layers in a layered architecture."}),"\n",(0,a.jsx)(t.p,{children:"Porto's rules and guidelines minimize and define the dependency directions between Containers, to avoid circular references between them."}),"\n",(0,a.jsx)(t.p,{children:"Additionally, it allows the grouping of related Containers, making it possible to reuse them in different projects. Each section contains a reusable portion of your application's business logic."}),"\n",(0,a.jsx)(t.p,{children:"When it comes to dependency management, the developer is free to move each Container to its own repository or keep all Containers together under a single repository."}),"\n",(0,a.jsx)(t.h2,{id:"maintainability--scalability",children:"Maintainability & Scalability"}),"\n",(0,a.jsx)(t.p,{children:"Porto aims to reduce maintenance costs by saving developers time. It's structured in a way to ensure code decoupling and forces consistency, which all contribute to its maintainability."}),"\n",(0,a.jsx)(t.p,{children:"Having a single function per class to describe a functionality makes adding and removing features an easy process."}),"\n",(0,a.jsx)(t.p,{children:"Porto has a very organized codebase and zero code coupling. In addition to a clear development workflow with predefined data flow and dependencies directions, all of these contribute to its scalability."}),"\n",(0,a.jsx)(t.h2,{id:"testability--debuggability",children:"Testability & Debuggability"}),"\n",(0,a.jsx)(t.p,{children:"Extremely adhering to the single responsibility principle by having a single function per class results in having slim classes, which leads to easier testability."}),"\n",(0,a.jsx)(t.p,{children:"In Porto, each component expects the same type of input and output,\nwhich makes testing, mocking, and stabbing straightforward."}),"\n",(0,a.jsxs)(t.p,{children:["The Porto structure itself makes writing automated tests a smooth process. Each container has a ",(0,a.jsx)(t.code,{children:"tests"})," folder at its root to contain unit tests for its tasks. Additionally, each UI folder has a ",(0,a.jsx)(t.code,{children:"tests"})," folder to contain functional tests (for testing each UI separately)."]}),"\n",(0,a.jsx)(t.p,{children:"The key to making testing and debugging easy is not only in the organization of the tests and the predefined responsibility of the components, but also in the decoupling of your code."}),"\n",(0,a.jsx)(t.h2,{id:"adaptability--evolvability",children:"Adaptability & Evolvability"}),"\n",(0,a.jsx)(t.p,{children:"Porto allows for easy accommodation of future changes with minimal effort."}),"\n",(0,a.jsx)(t.p,{children:"For example, let's say you have a web app that serves HTML and you decide that you also need a mobile app with an API. Porto's pluggable UI's (WEB, API & CLI) enables you to write the business logic of your application first and then implement a UI to interact with your code. This gives you the flexibility to add interfaces as needed and adapt to future changes with ease."}),"\n",(0,a.jsx)(t.p,{children:"The reason this is possible is that Actions are the central organizing principle, not the controller,\nand they can be shared across multiple UI's.\nAdditionally,\nthe UI's are separated from the application business logic and separated from each other within each Container."}),"\n",(0,a.jsx)(t.h2,{id:"usability--learnability",children:"Usability & Learnability"}),"\n",(0,a.jsx)(t.p,{children:"Porto prioritizes ease of use and understandability. Its implementation of domain expert language when naming classes and adherence to the single function per class rule allow for quick location of any feature or functionality. This means that you can easily find any Use Case (Action) in your code simply by browsing the files."}),"\n",(0,a.jsx)(t.p,{children:"Porto guarantees that you can find any feature implementation in less than 3 seconds. For example, if you are looking for where user addresses are being validated, simply go to the Address Container, open the list of Actions, and search for the ValidateUserAddressAction."}),"\n",(0,a.jsx)(t.h2,{id:"extensibility--flexibility",children:"Extensibility & Flexibility"}),"\n",(0,a.jsx)(t.p,{children:'Porto takes future growth into consideration and ensures your code remains maintainable no matter how large the project becomes. Its modular structure, separation of concerns, and organized coupling between internal classes ("Components") allows for modifications to be made without undesirable side effects.'}),"\n",(0,a.jsx)(t.p,{children:"Furthermore, Porto's extensibility and flexibility allow for easy integration with other tools and technologies. Its modular structure enables the addition of new functionality without affecting existing code, making it easy to scale the project as needed. This means that Porto is not only a great choice for current projects, but also for those that may require additional features or integrations in the future. The flexibility provided by Porto also allows for easy customization of the codebase to fit specific project requirements. This makes it a versatile choice for a wide range of development needs."}),"\n",(0,a.jsx)(t.h2,{id:"agility--upgradability",children:"Agility & Upgradability"}),"\n",(0,a.jsx)(t.p,{children:"Porto enables quick and easy movement in the development process."}),"\n",(0,a.jsx)(t.p,{children:"Upgrading the framework is straightforward due to the complete separation between the application and framework code through the Ship layer."}),"\n",(0,a.jsx)(t.p,{children:"Additionally, Porto's pluggable UI's make it easy to add or remove interfaces, and its modular structure enables adding new features or modifying existing ones without causing negative impacts on other parts of the codebase. This agility and upgradability make Porto a great choice for projects that require flexibility and adaptability to future changes."}),"\n",(0,a.jsx)("img",{src:"/Porto/img/porto_ship_2.png",alt:"Porto Components",style:{width:"100%"}})]})}function u(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>s,x:()=>r});var a=i(6540);const n={},o=a.createContext(n);function s(e){const t=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:s(e.components),a.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c7e95178.f5a99dea.js b/assets/js/c7e95178.f5a99dea.js deleted file mode 100644 index 90e83e3..0000000 --- a/assets/js/c7e95178.f5a99dea.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkporto=self.webpackChunkporto||[]).push([[884],{3610:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>l,contentTitle:()=>s,default:()=>h,frontMatter:()=>o,metadata:()=>r,toc:()=>d});var a=i(4848),n=i(8453);const o={sidebar_position:7},s="Quality Attributes",r={id:"Quality Attributes",title:"Quality Attributes",description:"Quality attributes are integral to Porto's design and implementation. They ensure the software meets the needs and expectations of its developers.",source:"@site/docs/Quality Attributes.md",sourceDirName:".",slug:"/Quality Attributes",permalink:"/Porto/docs/Quality Attributes",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/Quality Attributes.md",tags:[],version:"current",sidebarPosition:7,frontMatter:{sidebar_position:7},sidebar:"tutorialSidebar",previous:{title:"Monolithic to Microservices",permalink:"/Porto/docs/Features/Monolithic to MicroServices"},next:{title:"Implementations",permalink:"/Porto/docs/Implementations"}},l={},d=[{value:"Modularity & Reusability",id:"modularity--reusability",level:2},{value:"Maintainability & Scalability",id:"maintainability--scalability",level:2},{value:"Testability & Debuggability",id:"testability--debuggability",level:2},{value:"Adaptability & Evolvability",id:"adaptability--evolvability",level:2},{value:"Usability & Learnability",id:"usability--learnability",level:2},{value:"Extensibility & Flexibility",id:"extensibility--flexibility",level:2},{value:"Agility & Upgradability",id:"agility--upgradability",level:2}];function c(e){const t={code:"code",em:"em",h1:"h1",h2:"h2",hr:"hr",p:"p",...(0,n.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.h1,{id:"quality-attributes",children:"Quality Attributes"}),"\n",(0,a.jsx)(t.p,{children:"Quality attributes are integral to Porto's design and implementation. They ensure the software meets the needs and expectations of its developers."}),"\n",(0,a.jsx)(t.hr,{}),"\n",(0,a.jsx)(t.h2,{id:"modularity--reusability",children:"Modularity & Reusability"}),"\n",(0,a.jsxs)(t.p,{children:["In Porto, your application business logic lives in Containers. Porto Containers are similar in nature to the Modules ",(0,a.jsx)(t.em,{children:"(from the Modular architecture)"})," and Domains ",(0,a.jsx)(t.em,{children:"(from the DDD architecture)"}),"."]}),"\n",(0,a.jsx)(t.p,{children:"Containers can depend on other Containers, similar to how a layer can depend on other layers in a layered architecture."}),"\n",(0,a.jsx)(t.p,{children:"Porto's rules and guidelines minimize and define the dependency directions between Containers, to avoid circular references between them."}),"\n",(0,a.jsx)(t.p,{children:"Additionally, it allows the grouping of related Containers, making it possible to reuse them in different projects. Each section contains a reusable portion of your application's business logic."}),"\n",(0,a.jsx)(t.p,{children:"When it comes to dependency management, the developer is free to move each Container to its own repository or keep all Containers together under a single repository."}),"\n",(0,a.jsx)(t.hr,{}),"\n",(0,a.jsx)(t.h2,{id:"maintainability--scalability",children:"Maintainability & Scalability"}),"\n",(0,a.jsx)(t.p,{children:"Porto aims to reduce maintenance costs by saving developers time. It's structured in a way to ensure code decoupling and forces consistency, which all contribute to its maintainability."}),"\n",(0,a.jsx)(t.p,{children:"Having a single function per class to describe a functionality makes adding and removing features an easy process."}),"\n",(0,a.jsx)(t.p,{children:"Porto has a very organized codebase and zero code coupling. In addition to a clear development workflow with predefined data flow and dependencies directions, all of these contribute to its scalability."}),"\n",(0,a.jsx)(t.hr,{}),"\n",(0,a.jsx)(t.h2,{id:"testability--debuggability",children:"Testability & Debuggability"}),"\n",(0,a.jsx)(t.p,{children:"Extremely adhering to the single responsibility principle by having a single function per class results in having slim classes, which leads to easier testability."}),"\n",(0,a.jsx)(t.p,{children:"In Porto, each component expects the same type of input and output,\nwhich makes testing, mocking, and stabbing straightforward."}),"\n",(0,a.jsxs)(t.p,{children:["The Porto structure itself makes writing automated tests a smooth process. Each container has a ",(0,a.jsx)(t.code,{children:"tests"})," folder at its root to contain unit tests for its tasks. Additionally, each UI folder has a ",(0,a.jsx)(t.code,{children:"tests"})," folder to contain functional tests (for testing each UI separately)."]}),"\n",(0,a.jsx)(t.p,{children:"The key to making testing and debugging easy is not only in the organization of the tests and the predefined responsibility of the components, but also in the decoupling of your code."}),"\n",(0,a.jsx)(t.hr,{}),"\n",(0,a.jsx)(t.h2,{id:"adaptability--evolvability",children:"Adaptability & Evolvability"}),"\n",(0,a.jsx)(t.p,{children:"Porto allows for easy accommodation of future changes with minimal effort."}),"\n",(0,a.jsx)(t.p,{children:"For example, let's say you have a web app that serves HTML and you decide that you also need a mobile app with an API. Porto's pluggable UI's (WEB, API & CLI) enables you to write the business logic of your application first and then implement a UI to interact with your code. This gives you the flexibility to add interfaces as needed and adapt to future changes with ease."}),"\n",(0,a.jsx)(t.p,{children:"The reason this is possible is that Actions are the central organizing principle, not the controller,\nand they can be shared across multiple UI's.\nAdditionally,\nthe UI's are separated from the application business logic and separated from each other within each Container."}),"\n",(0,a.jsx)(t.hr,{}),"\n",(0,a.jsx)(t.h2,{id:"usability--learnability",children:"Usability & Learnability"}),"\n",(0,a.jsx)(t.p,{children:"Porto prioritizes ease of use and understandability. Its implementation of domain expert language when naming classes and adherence to the single function per class rule allow for quick location of any feature or functionality. This means that you can easily find any Use Case (Action) in your code simply by browsing the files."}),"\n",(0,a.jsx)(t.p,{children:"Porto guarantees that you can find any feature implementation in less than 3 seconds. For example, if you are looking for where user addresses are being validated, simply go to the Address Container, open the list of Actions, and search for the ValidateUserAddressAction."}),"\n",(0,a.jsx)(t.hr,{}),"\n",(0,a.jsx)(t.h2,{id:"extensibility--flexibility",children:"Extensibility & Flexibility"}),"\n",(0,a.jsx)(t.p,{children:'Porto takes future growth into consideration and ensures your code remains maintainable no matter how large the project becomes. Its modular structure, separation of concerns, and organized coupling between internal classes ("Components") allows for modifications to be made without undesirable side effects.'}),"\n",(0,a.jsx)(t.p,{children:"Furthermore, Porto's extensibility and flexibility allow for easy integration with other tools and technologies. Its modular structure enables the addition of new functionality without affecting existing code, making it easy to scale the project as needed. This means that Porto is not only a great choice for current projects, but also for those that may require additional features or integrations in the future. The flexibility provided by Porto also allows for easy customization of the codebase to fit specific project requirements. This makes it a versatile choice for a wide range of development needs."}),"\n",(0,a.jsx)(t.hr,{}),"\n",(0,a.jsx)(t.h2,{id:"agility--upgradability",children:"Agility & Upgradability"}),"\n",(0,a.jsx)(t.p,{children:"Porto enables quick and easy movement in the development process."}),"\n",(0,a.jsx)(t.p,{children:"Upgrading the framework is straightforward due to the complete separation between the application and framework code through the Ship layer."}),"\n",(0,a.jsx)(t.p,{children:"Additionally, Porto's pluggable UI's make it easy to add or remove interfaces, and its modular structure enables adding new features or modifying existing ones without causing negative impacts on other parts of the codebase. This agility and upgradability make Porto a great choice for projects that require flexibility and adaptability to future changes."}),"\n",(0,a.jsx)(t.hr,{})]})}function h(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>s,x:()=>r});var a=i(6540);const n={},o=a.createContext(n);function s(e){const t=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:s(e.components),a.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/runtime~main.83826f14.js b/assets/js/runtime~main.eb97f91e.js similarity index 96% rename from assets/js/runtime~main.83826f14.js rename to assets/js/runtime~main.eb97f91e.js index d42b40c..27dbe31 100644 --- a/assets/js/runtime~main.83826f14.js +++ b/assets/js/runtime~main.eb97f91e.js @@ -1 +1 @@ -(()=>{"use strict";var e,a,t,r,f,c={},o={};function b(e){var a=o[e];if(void 0!==a)return a.exports;var t=o[e]={id:e,loaded:!1,exports:{}};return c[e].call(t.exports,t,t.exports,b),t.loaded=!0,t.exports}b.m=c,b.c=o,e=[],b.O=(a,t,r,f)=>{if(!t){var c=1/0;for(i=0;i=f)&&Object.keys(b.O).every((e=>b.O[e](t[d])))?t.splice(d--,1):(o=!1,f0&&e[i-1][2]>f;i--)e[i]=e[i-1];e[i]=[t,r,f]},b.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return b.d(a,{a:a}),a},t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,b.t=function(e,r){if(1&r&&(e=this(e)),8&r)return e;if("object"==typeof e&&e){if(4&r&&e.__esModule)return e;if(16&r&&"function"==typeof e.then)return e}var f=Object.create(null);b.r(f);var c={};a=a||[null,t({}),t([]),t(t)];for(var o=2&r&&e;"object"==typeof o&&!~a.indexOf(o);o=t(o))Object.getOwnPropertyNames(o).forEach((a=>c[a]=()=>e[a]));return c.default=()=>e,b.d(f,c),f},b.d=(e,a)=>{for(var t in a)b.o(a,t)&&!b.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:a[t]})},b.f={},b.e=e=>Promise.all(Object.keys(b.f).reduce(((a,t)=>(b.f[t](e,a),a)),[])),b.u=e=>"assets/js/"+({48:"a94703ab",55:"d41fe019",56:"b00ef024",61:"1f391b9e",62:"53c600db",98:"a7bd4aaa",134:"393be207",160:"49a2a3be",182:"bdcc1c16",216:"7a9d8534",235:"a7456010",322:"133ef37a",328:"911175fa",369:"19565b40",387:"57ae60ca",397:"f490af68",401:"17896441",416:"2cff5ebb",418:"267d4f7c",420:"0067bd39",503:"9dcca34e",553:"7a3a4712",562:"477ebb77",583:"1df93b7f",592:"175cb08e",602:"070e66cf",629:"7fc7d546",647:"5e95c892",661:"377ca38f",662:"50f32cfd",742:"aba21aa0",755:"94f544fb",796:"2cc8d2b3",813:"c0fbb908",833:"798d4569",884:"c7e95178",887:"617f6486",896:"0d296b2f",930:"af822310",969:"14eb3368",985:"85acc9a4",995:"26121f2b"}[e]||e)+"."+{48:"168d7fdb",55:"7446b4f3",56:"9ab906c8",61:"f8b7adc5",62:"5a18eb56",98:"45295ff3",134:"e8a04114",160:"2d16fdae",182:"c8ebb16a",216:"ce9dc142",235:"1d868e7f",237:"77332594",322:"84c9677c",328:"dbed2764",369:"50c95e99",387:"0b3ae99a",397:"2a03caa2",401:"d28c2ec6",416:"78464a41",418:"6cb039e3",420:"a2516b3e",503:"df9cb93a",553:"ffd5adc8",562:"994503b4",583:"49a82c1f",592:"53f61480",602:"6b1932bb",629:"d8debcca",647:"638e2932",658:"e5deb26b",661:"1aeb167f",662:"251e64a3",742:"03552889",755:"7c13f2d0",796:"6732715e",813:"ac463d61",833:"8dcc6b52",884:"f5a99dea",887:"525be4d3",896:"218e0270",930:"5012182b",969:"a3e7b01d",985:"5fb59afe",995:"2aeb2b3d"}[e]+".js",b.miniCssF=e=>{},b.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),b.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),r={},f="porto:",b.l=(e,a,t,c)=>{if(r[e])r[e].push(a);else{var o,d;if(void 0!==t)for(var n=document.getElementsByTagName("script"),i=0;i{o.onerror=o.onload=null,clearTimeout(s);var f=r[e];if(delete r[e],o.parentNode&&o.parentNode.removeChild(o),f&&f.forEach((e=>e(t))),a)return a(t)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:o}),12e4);o.onerror=l.bind(null,o.onerror),o.onload=l.bind(null,o.onload),d&&document.head.appendChild(o)}},b.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},b.p="/Porto/",b.gca=function(e){return e={17896441:"401",a94703ab:"48",d41fe019:"55",b00ef024:"56","1f391b9e":"61","53c600db":"62",a7bd4aaa:"98","393be207":"134","49a2a3be":"160",bdcc1c16:"182","7a9d8534":"216",a7456010:"235","133ef37a":"322","911175fa":"328","19565b40":"369","57ae60ca":"387",f490af68:"397","2cff5ebb":"416","267d4f7c":"418","0067bd39":"420","9dcca34e":"503","7a3a4712":"553","477ebb77":"562","1df93b7f":"583","175cb08e":"592","070e66cf":"602","7fc7d546":"629","5e95c892":"647","377ca38f":"661","50f32cfd":"662",aba21aa0:"742","94f544fb":"755","2cc8d2b3":"796",c0fbb908:"813","798d4569":"833",c7e95178:"884","617f6486":"887","0d296b2f":"896",af822310:"930","14eb3368":"969","85acc9a4":"985","26121f2b":"995"}[e]||e,b.p+b.u(e)},(()=>{var e={354:0,869:0};b.f.j=(a,t)=>{var r=b.o(e,a)?e[a]:void 0;if(0!==r)if(r)t.push(r[2]);else if(/^(354|869)$/.test(a))e[a]=0;else{var f=new Promise(((t,f)=>r=e[a]=[t,f]));t.push(r[2]=f);var c=b.p+b.u(a),o=new Error;b.l(c,(t=>{if(b.o(e,a)&&(0!==(r=e[a])&&(e[a]=void 0),r)){var f=t&&("load"===t.type?"missing":t.type),c=t&&t.target&&t.target.src;o.message="Loading chunk "+a+" failed.\n("+f+": "+c+")",o.name="ChunkLoadError",o.type=f,o.request=c,r[1](o)}}),"chunk-"+a,a)}},b.O.j=a=>0===e[a];var a=(a,t)=>{var r,f,c=t[0],o=t[1],d=t[2],n=0;if(c.some((a=>0!==e[a]))){for(r in o)b.o(o,r)&&(b.m[r]=o[r]);if(d)var i=d(b)}for(a&&a(t);n{"use strict";var e,a,t,r,f,c={},o={};function b(e){var a=o[e];if(void 0!==a)return a.exports;var t=o[e]={id:e,loaded:!1,exports:{}};return c[e].call(t.exports,t,t.exports,b),t.loaded=!0,t.exports}b.m=c,b.c=o,e=[],b.O=(a,t,r,f)=>{if(!t){var c=1/0;for(i=0;i=f)&&Object.keys(b.O).every((e=>b.O[e](t[d])))?t.splice(d--,1):(o=!1,f0&&e[i-1][2]>f;i--)e[i]=e[i-1];e[i]=[t,r,f]},b.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return b.d(a,{a:a}),a},t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,b.t=function(e,r){if(1&r&&(e=this(e)),8&r)return e;if("object"==typeof e&&e){if(4&r&&e.__esModule)return e;if(16&r&&"function"==typeof e.then)return e}var f=Object.create(null);b.r(f);var c={};a=a||[null,t({}),t([]),t(t)];for(var o=2&r&&e;"object"==typeof o&&!~a.indexOf(o);o=t(o))Object.getOwnPropertyNames(o).forEach((a=>c[a]=()=>e[a]));return c.default=()=>e,b.d(f,c),f},b.d=(e,a)=>{for(var t in a)b.o(a,t)&&!b.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:a[t]})},b.f={},b.e=e=>Promise.all(Object.keys(b.f).reduce(((a,t)=>(b.f[t](e,a),a)),[])),b.u=e=>"assets/js/"+({48:"a94703ab",55:"d41fe019",56:"b00ef024",61:"1f391b9e",62:"53c600db",98:"a7bd4aaa",134:"393be207",160:"49a2a3be",182:"bdcc1c16",216:"7a9d8534",235:"a7456010",322:"133ef37a",328:"911175fa",369:"19565b40",387:"57ae60ca",397:"f490af68",401:"17896441",416:"2cff5ebb",418:"267d4f7c",420:"0067bd39",503:"9dcca34e",553:"7a3a4712",562:"477ebb77",583:"1df93b7f",592:"175cb08e",602:"070e66cf",629:"7fc7d546",647:"5e95c892",661:"377ca38f",662:"50f32cfd",742:"aba21aa0",755:"94f544fb",796:"2cc8d2b3",813:"c0fbb908",833:"798d4569",884:"c7e95178",887:"617f6486",896:"0d296b2f",930:"af822310",969:"14eb3368",985:"85acc9a4",995:"26121f2b"}[e]||e)+"."+{48:"168d7fdb",55:"7446b4f3",56:"9ab906c8",61:"f8b7adc5",62:"5a18eb56",98:"45295ff3",134:"e8a04114",160:"2d16fdae",182:"c8ebb16a",216:"ce9dc142",235:"1d868e7f",237:"77332594",322:"84c9677c",328:"dbed2764",369:"50c95e99",387:"0b3ae99a",397:"2a03caa2",401:"d28c2ec6",416:"78464a41",418:"6cb039e3",420:"a2516b3e",503:"df9cb93a",553:"ffd5adc8",562:"994503b4",583:"49a82c1f",592:"53f61480",602:"6b1932bb",629:"d8debcca",647:"638e2932",658:"e5deb26b",661:"d1335c14",662:"251e64a3",742:"03552889",755:"7c13f2d0",796:"6732715e",813:"ac463d61",833:"8dcc6b52",884:"c0f2de20",887:"525be4d3",896:"218e0270",930:"5012182b",969:"a3e7b01d",985:"5fb59afe",995:"2aeb2b3d"}[e]+".js",b.miniCssF=e=>{},b.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),b.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),r={},f="porto:",b.l=(e,a,t,c)=>{if(r[e])r[e].push(a);else{var o,d;if(void 0!==t)for(var n=document.getElementsByTagName("script"),i=0;i{o.onerror=o.onload=null,clearTimeout(s);var f=r[e];if(delete r[e],o.parentNode&&o.parentNode.removeChild(o),f&&f.forEach((e=>e(t))),a)return a(t)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:o}),12e4);o.onerror=l.bind(null,o.onerror),o.onload=l.bind(null,o.onload),d&&document.head.appendChild(o)}},b.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},b.p="/Porto/",b.gca=function(e){return e={17896441:"401",a94703ab:"48",d41fe019:"55",b00ef024:"56","1f391b9e":"61","53c600db":"62",a7bd4aaa:"98","393be207":"134","49a2a3be":"160",bdcc1c16:"182","7a9d8534":"216",a7456010:"235","133ef37a":"322","911175fa":"328","19565b40":"369","57ae60ca":"387",f490af68:"397","2cff5ebb":"416","267d4f7c":"418","0067bd39":"420","9dcca34e":"503","7a3a4712":"553","477ebb77":"562","1df93b7f":"583","175cb08e":"592","070e66cf":"602","7fc7d546":"629","5e95c892":"647","377ca38f":"661","50f32cfd":"662",aba21aa0:"742","94f544fb":"755","2cc8d2b3":"796",c0fbb908:"813","798d4569":"833",c7e95178:"884","617f6486":"887","0d296b2f":"896",af822310:"930","14eb3368":"969","85acc9a4":"985","26121f2b":"995"}[e]||e,b.p+b.u(e)},(()=>{var e={354:0,869:0};b.f.j=(a,t)=>{var r=b.o(e,a)?e[a]:void 0;if(0!==r)if(r)t.push(r[2]);else if(/^(354|869)$/.test(a))e[a]=0;else{var f=new Promise(((t,f)=>r=e[a]=[t,f]));t.push(r[2]=f);var c=b.p+b.u(a),o=new Error;b.l(c,(t=>{if(b.o(e,a)&&(0!==(r=e[a])&&(e[a]=void 0),r)){var f=t&&("load"===t.type?"missing":t.type),c=t&&t.target&&t.target.src;o.message="Loading chunk "+a+" failed.\n("+f+": "+c+")",o.name="ChunkLoadError",o.type=f,o.request=c,r[1](o)}}),"chunk-"+a,a)}},b.O.j=a=>0===e[a];var a=(a,t)=>{var r,f,c=t[0],o=t[1],d=t[2],n=0;if(c.some((a=>0!==e[a]))){for(r in o)b.o(o,r)&&(b.m[r]=o[r]);if(d)var i=d(b)}for(a&&a(t);n Author | Porto SAP - + diff --git a/docs/Basics/Components Interaction/index.html b/docs/Basics/Components Interaction/index.html index c65860b..74d0fde 100644 --- a/docs/Basics/Components Interaction/index.html +++ b/docs/Basics/Components Interaction/index.html @@ -4,7 +4,7 @@ Components Interaction | Porto SAP - + diff --git a/docs/Basics/Containers Dependencies/index.html b/docs/Basics/Containers Dependencies/index.html index 677cf88..5769e3a 100644 --- a/docs/Basics/Containers Dependencies/index.html +++ b/docs/Basics/Containers Dependencies/index.html @@ -4,7 +4,7 @@ Containers Dependencies | Porto SAP - + diff --git a/docs/Basics/Data Flow/index.html b/docs/Basics/Data Flow/index.html index 2db9cac..aa6f923 100644 --- a/docs/Basics/Data Flow/index.html +++ b/docs/Basics/Data Flow/index.html @@ -4,7 +4,7 @@ Data Flow | Porto SAP - + diff --git a/docs/Components/Components Overview/index.html b/docs/Components/Components Overview/index.html index c9e90ef..e9940ed 100644 --- a/docs/Components/Components Overview/index.html +++ b/docs/Components/Components Overview/index.html @@ -4,7 +4,7 @@ Components Overview | Porto SAP - + diff --git a/docs/Components/Main Components Principles/Actions/index.html b/docs/Components/Main Components Principles/Actions/index.html index cc0b5e3..2dcb921 100644 --- a/docs/Components/Main Components Principles/Actions/index.html +++ b/docs/Components/Main Components Principles/Actions/index.html @@ -4,7 +4,7 @@ Actions | Porto SAP - + diff --git a/docs/Components/Main Components Principles/Controllers/index.html b/docs/Components/Main Components Principles/Controllers/index.html index 5edd4e7..4af56d6 100644 --- a/docs/Components/Main Components Principles/Controllers/index.html +++ b/docs/Components/Main Components Principles/Controllers/index.html @@ -4,7 +4,7 @@ Controllers | Porto SAP - + diff --git a/docs/Components/Main Components Principles/Exceptions/index.html b/docs/Components/Main Components Principles/Exceptions/index.html index 64daf46..ce7bc75 100644 --- a/docs/Components/Main Components Principles/Exceptions/index.html +++ b/docs/Components/Main Components Principles/Exceptions/index.html @@ -4,7 +4,7 @@ Exceptions | Porto SAP - + diff --git a/docs/Components/Main Components Principles/Models/index.html b/docs/Components/Main Components Principles/Models/index.html index 1f3ea0a..2c5f86a 100644 --- a/docs/Components/Main Components Principles/Models/index.html +++ b/docs/Components/Main Components Principles/Models/index.html @@ -4,7 +4,7 @@ Models | Porto SAP - + diff --git a/docs/Components/Main Components Principles/Requests/index.html b/docs/Components/Main Components Principles/Requests/index.html index 14839fa..35997c8 100644 --- a/docs/Components/Main Components Principles/Requests/index.html +++ b/docs/Components/Main Components Principles/Requests/index.html @@ -4,7 +4,7 @@ Requests | Porto SAP - + diff --git a/docs/Components/Main Components Principles/Routes/index.html b/docs/Components/Main Components Principles/Routes/index.html index da32a41..6ca7cb5 100644 --- a/docs/Components/Main Components Principles/Routes/index.html +++ b/docs/Components/Main Components Principles/Routes/index.html @@ -4,7 +4,7 @@ Routes | Porto SAP - + diff --git a/docs/Components/Main Components Principles/Sub-Actions/index.html b/docs/Components/Main Components Principles/Sub-Actions/index.html index 132adef..9b3b6dc 100644 --- a/docs/Components/Main Components Principles/Sub-Actions/index.html +++ b/docs/Components/Main Components Principles/Sub-Actions/index.html @@ -4,7 +4,7 @@ Sub-Actions | Porto SAP - + diff --git a/docs/Components/Main Components Principles/Tasks/index.html b/docs/Components/Main Components Principles/Tasks/index.html index bb393ff..5aa8d12 100644 --- a/docs/Components/Main Components Principles/Tasks/index.html +++ b/docs/Components/Main Components Principles/Tasks/index.html @@ -4,7 +4,7 @@ Tasks | Porto SAP - + diff --git a/docs/Components/Main Components Principles/Transformers/index.html b/docs/Components/Main Components Principles/Transformers/index.html index eb85e91..2a1cd72 100644 --- a/docs/Components/Main Components Principles/Transformers/index.html +++ b/docs/Components/Main Components Principles/Transformers/index.html @@ -4,7 +4,7 @@ Transformers | Porto SAP - + diff --git a/docs/Components/Main Components Principles/Views/index.html b/docs/Components/Main Components Principles/Views/index.html index e3f8cf8..deab90b 100644 --- a/docs/Components/Main Components Principles/Views/index.html +++ b/docs/Components/Main Components Principles/Views/index.html @@ -4,7 +4,7 @@ Views | Porto SAP - + diff --git a/docs/Components/Optional Components/index.html b/docs/Components/Optional Components/index.html index 4f5a2aa..63abfd9 100644 --- a/docs/Components/Optional Components/index.html +++ b/docs/Components/Optional Components/index.html @@ -4,7 +4,7 @@ Optional Components | Porto SAP - + diff --git a/docs/Donations/index.html b/docs/Donations/index.html index 779aa74..18b88c5 100644 --- a/docs/Donations/index.html +++ b/docs/Donations/index.html @@ -4,7 +4,7 @@ Donations | Porto SAP - + diff --git a/docs/Features/AI Driven Development/index.html b/docs/Features/AI Driven Development/index.html index fab1a5c..c4ed21b 100644 --- a/docs/Features/AI Driven Development/index.html +++ b/docs/Features/AI Driven Development/index.html @@ -4,7 +4,7 @@ AI-Driven Development | Porto SAP - + diff --git a/docs/Features/Monolithic to MicroServices/index.html b/docs/Features/Monolithic to MicroServices/index.html index ec3c978..57537b6 100644 --- a/docs/Features/Monolithic to MicroServices/index.html +++ b/docs/Features/Monolithic to MicroServices/index.html @@ -4,7 +4,7 @@ Monolithic to Microservices | Porto SAP - + diff --git a/docs/Feedback/index.html b/docs/Feedback/index.html index 7c235ed..bf8a10e 100644 --- a/docs/Feedback/index.html +++ b/docs/Feedback/index.html @@ -4,7 +4,7 @@ Feedback | Porto SAP - + diff --git a/docs/Implementations/index.html b/docs/Implementations/index.html index 5c50504..6d30655 100644 --- a/docs/Implementations/index.html +++ b/docs/Implementations/index.html @@ -4,7 +4,7 @@ Implementations | Porto SAP - + diff --git a/docs/Intro/index.html b/docs/Intro/index.html index 7cb9ca7..7d04978 100644 --- a/docs/Intro/index.html +++ b/docs/Intro/index.html @@ -4,7 +4,7 @@ Introduction | Porto SAP - + @@ -14,7 +14,7 @@

Overview

Porto is a modern software architectural pattern providing a robust framework of guidelines, principles, and patterns. It is designed to facilitate the creation of software that is scalable, maintainable, and reusable. Porto allows you to start with a clean monolith and expand to microservices as needed, thanks to its modular structure which facilitates easy scaling and separation of concerns. Its adherence to the single responsibility principle enhances its integration with AI tools like GitHub Copilot, aiding in feature development, debugging, and more.

-Porto Components +Porto Components

Foundation

Porto is grounded in established architectural concepts such as Domain Driven Design (DDD), Modular, Micro Kernel, Model View Controller (MVC), Layered, and Action Domain Responder (ADR). It supports principles including SOLID, OOP, LIFT, DRY, CoC, GRASP, Generalization, High Cohesion, and Low Coupling. These principles ensure that systems built with Porto are not only maintainable and scalable but also straightforward and comprehensible.

Benefits

diff --git a/docs/Layers/Containers Layer/index.html b/docs/Layers/Containers Layer/index.html index 7c8b8cd..7de24d5 100644 --- a/docs/Layers/Containers Layer/index.html +++ b/docs/Layers/Containers Layer/index.html @@ -4,7 +4,7 @@ Containers Layer | Porto SAP - + diff --git a/docs/Layers/Layers Overview/index.html b/docs/Layers/Layers Overview/index.html index 8245a7f..425936f 100644 --- a/docs/Layers/Layers Overview/index.html +++ b/docs/Layers/Layers Overview/index.html @@ -4,7 +4,7 @@ Layers Overview | Porto SAP - + diff --git a/docs/Layers/Ship Layer/index.html b/docs/Layers/Ship Layer/index.html index d980aae..10c8b37 100644 --- a/docs/Layers/Ship Layer/index.html +++ b/docs/Layers/Ship Layer/index.html @@ -4,7 +4,7 @@ Ship Layer | Porto SAP - + diff --git a/docs/Quality Attributes/index.html b/docs/Quality Attributes/index.html index a6cff3b..f8af076 100644 --- a/docs/Quality Attributes/index.html +++ b/docs/Quality Attributes/index.html @@ -4,32 +4,28 @@ Quality Attributes | Porto SAP - +

Quality Attributes

Quality attributes are integral to Porto's design and implementation. They ensure the software meets the needs and expectations of its developers.

-

Modularity & Reusability

In Porto, your application business logic lives in Containers. Porto Containers are similar in nature to the Modules (from the Modular architecture) and Domains (from the DDD architecture).

Containers can depend on other Containers, similar to how a layer can depend on other layers in a layered architecture.

Porto's rules and guidelines minimize and define the dependency directions between Containers, to avoid circular references between them.

Additionally, it allows the grouping of related Containers, making it possible to reuse them in different projects. Each section contains a reusable portion of your application's business logic.

When it comes to dependency management, the developer is free to move each Container to its own repository or keep all Containers together under a single repository.

-

Maintainability & Scalability

Porto aims to reduce maintenance costs by saving developers time. It's structured in a way to ensure code decoupling and forces consistency, which all contribute to its maintainability.

Having a single function per class to describe a functionality makes adding and removing features an easy process.

Porto has a very organized codebase and zero code coupling. In addition to a clear development workflow with predefined data flow and dependencies directions, all of these contribute to its scalability.

-

Testability & Debuggability

Extremely adhering to the single responsibility principle by having a single function per class results in having slim classes, which leads to easier testability.

In Porto, each component expects the same type of input and output, which makes testing, mocking, and stabbing straightforward.

The Porto structure itself makes writing automated tests a smooth process. Each container has a tests folder at its root to contain unit tests for its tasks. Additionally, each UI folder has a tests folder to contain functional tests (for testing each UI separately).

The key to making testing and debugging easy is not only in the organization of the tests and the predefined responsibility of the components, but also in the decoupling of your code.

-

Adaptability & Evolvability

Porto allows for easy accommodation of future changes with minimal effort.

For example, let's say you have a web app that serves HTML and you decide that you also need a mobile app with an API. Porto's pluggable UI's (WEB, API & CLI) enables you to write the business logic of your application first and then implement a UI to interact with your code. This gives you the flexibility to add interfaces as needed and adapt to future changes with ease.

@@ -37,19 +33,16 @@

A and they can be shared across multiple UI's. Additionally, the UI's are separated from the application business logic and separated from each other within each Container.

-

Usability & Learnability

Porto prioritizes ease of use and understandability. Its implementation of domain expert language when naming classes and adherence to the single function per class rule allow for quick location of any feature or functionality. This means that you can easily find any Use Case (Action) in your code simply by browsing the files.

Porto guarantees that you can find any feature implementation in less than 3 seconds. For example, if you are looking for where user addresses are being validated, simply go to the Address Container, open the list of Actions, and search for the ValidateUserAddressAction.

-

Extensibility & Flexibility

Porto takes future growth into consideration and ensures your code remains maintainable no matter how large the project becomes. Its modular structure, separation of concerns, and organized coupling between internal classes ("Components") allows for modifications to be made without undesirable side effects.

Furthermore, Porto's extensibility and flexibility allow for easy integration with other tools and technologies. Its modular structure enables the addition of new functionality without affecting existing code, making it easy to scale the project as needed. This means that Porto is not only a great choice for current projects, but also for those that may require additional features or integrations in the future. The flexibility provided by Porto also allows for easy customization of the codebase to fit specific project requirements. This makes it a versatile choice for a wide range of development needs.

-

Agility & Upgradability

Porto enables quick and easy movement in the development process.

Upgrading the framework is straightforward due to the complete separation between the application and framework code through the Ship layer.

Additionally, Porto's pluggable UI's make it easy to add or remove interfaces, and its modular structure enables adding new features or modifying existing ones without causing negative impacts on other parts of the codebase. This agility and upgradability make Porto a great choice for projects that require flexibility and adaptability to future changes.

-
+Porto Components \ No newline at end of file diff --git a/docs/category/basics/index.html b/docs/category/basics/index.html index 003078d..a0d408a 100644 --- a/docs/category/basics/index.html +++ b/docs/category/basics/index.html @@ -4,7 +4,7 @@ Basics | Porto SAP - + diff --git a/docs/category/components/index.html b/docs/category/components/index.html index 39271db..aac1f6c 100644 --- a/docs/category/components/index.html +++ b/docs/category/components/index.html @@ -4,7 +4,7 @@ Components | Porto SAP - + diff --git a/docs/category/features/index.html b/docs/category/features/index.html index 5f6fb0c..cb4dae1 100644 --- a/docs/category/features/index.html +++ b/docs/category/features/index.html @@ -4,7 +4,7 @@ Features | Porto SAP - + diff --git a/docs/category/layers/index.html b/docs/category/layers/index.html index 6bad81b..ede0fea 100644 --- a/docs/category/layers/index.html +++ b/docs/category/layers/index.html @@ -4,7 +4,7 @@ Layers | Porto SAP - + diff --git a/docs/category/main-components/index.html b/docs/category/main-components/index.html index 081a3a4..32bcf2a 100644 --- a/docs/category/main-components/index.html +++ b/docs/category/main-components/index.html @@ -4,7 +4,7 @@ Main Components | Porto SAP - + diff --git a/index.html b/index.html index d39e4ad..df9bc5f 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ Welcome to the Future of Backend Engineering Porto SAP | Porto SAP - + diff --git a/markdown-page/index.html b/markdown-page/index.html index b1ca04b..06cf172 100644 --- a/markdown-page/index.html +++ b/markdown-page/index.html @@ -4,7 +4,7 @@ Porto SAP PAGE | Porto SAP - +