blender視圖縮放
A concept to help Elm Views scale as applications grow larger and more complicated.
當應用程序變得更大和更復雜時,可幫助Elm Views擴展的概念。
In Elm, there are a lot of great ways to scale the Model
, and update
, but there is more controversy around scaling the view
. A lot of the debate is around Reusable Views versus Components. Components are not recommended, but a lot of people are still advocating for them. ?This article presents an idea that hopefully strengthens the argument for Resuable Views.
在Elm中,有很多很棒的方法可以縮放Model
和進行update
,但是圍繞縮放view
存在更多爭議。 關于可重用視圖與組件的爭論很多。 不建議使用組件,但是許多人仍在倡導使用它們。 本文提出了一個想法,希望能加強對可恢復觀點的爭論。
In almost all cases, the scaling problem comes down to enforcing consistency, which usually means allowing child views to make some adjustments to the master view, while at the same time not allowing child views to make a mess.
在幾乎所有情況下,縮放問題都歸結為強制執行一致性,這通常意味著允許子視圖對主視圖進行一些調整,而同時不允許子視圖造成混亂。
I will be using Richard Feldman's excellent Real World app (specifically written to demonstrate scaling in Elm) as an example, as it is contains a lot of current best practice techniques, it is well known (2000+ stars and 300+ forks) and Richard is a well known Elm expert.
我將以Richard Feldman出色的“ 真實世界”應用程序 (專門為演示Elm中的縮放比例而編寫)作為示例,因為它包含許多當前的最佳實踐技術,眾所周知(2000多顆星星和300多顆叉子)和Richard是一位著名的榆木專家。
I will be suggesting some improvements to this code, so I want make a clear at this point that I mean no disrespect by this (I would bet large sums of money that he did it in about one tenth of the time it would have taken me!). You could also argue that the problems are small and not worth fixing. Ultimately, this decision is yours, but by the end of the article I hope to persuade you that there are problems, and that they are fixable if you think it is worthwhile.
我將建議對此代碼進行一些改進,因此我想在此說明一下,我的意思是不要無視此事(我敢打賭,他花了大筆錢才花了我將近十分之一的時間) !)。 您還可以爭辯說問題很小,不值得解決。 最終,這是您的決定,但是到本文結尾,我希望說服您存在問題,并且如果您認為值得的話,這些問題是可以解決的。
具有條件的主視圖功能 (Master view functions with conditionals)
One option is to define a master view function. This function takes care of shared concerns, like the header bar and overall layout. Then it calls child view functions depending on the current view and / or has parameters to control child specific behaviour.
一種選擇是定義主視圖功能。 此功能可解決共享問題,例如標題欄和整體布局。 然后,它根據當前視圖調用子視圖函數,并且/或者具有控制子特定行為的參數。
This works, but can quickly lead to:
這行得通,但可以很快導致:
- An explosion of parameters, potentially forcing your child views to return a lot of things they don't care about. 參數的爆炸式增長,可能會迫使您的孩子視圖返回很多他們不在乎的東西。
- A mixing of responsibilities between master and child views. 主視圖和子視圖之間的職責混合。
- Extra code and duplication. 額外的代碼和重復。
In the Real World App, a parameter of type Page
is passed to the master view so that it can render a navbar link as active. There is a large case statement that uses this parameter to work out what which link is active, and it would be a lot easier for the child just to specify this.
在Real World App中,將Page
類型的參數傳遞到主視圖,以便它可以將導航欄鏈接呈現為活動狀態。 有一個大寫的語句使用此參數來確定哪個鏈接處于活動狀態,對于孩子來說,僅指定此鏈接會容易得多。
The line below shows the master view passing Page.Home
, which has to match up with Home.view home
. This is easy to get wrong, there is no help from the compiler or type system, and really it is the responsibility of the child view the specify this.
下面的行顯示了傳遞Page.Home
的主視圖,該視圖必須與Home.view home
匹配。 這很容易出錯,沒有來自編譯器或類型系統的幫助,這實際上是指定此子視圖的職責。
viewPage Page.Home GotHomeMsg (Home.view home)
viewPage Page.Home GotHomeMsg (Home.view home)
There is some duplication when creating the NavBarLink Html, and the linkTo
function will accept any Html, although only very particular Html is valid.
創建NavBarLink Html時會有一些重復,并且linkTo
函數將接受任何Html,盡管只有非常特殊的Html有效。
約定與信任 (Convention and trust)
Another possibility is for child views to be responsible for keeping shared elements consistent, by convention and trust.
子視圖的另一種可能性是根據約定和信任負責使共享元素保持一致。
Arguably this also happens in the Real World App. The Home, Article and Profile views all have the concept of a banner. The banner is different in each view, but presumably is meant to be a consistent and recognisable visual element (essentially, it's the title / header for the view). The views don't share any code for these banners, and as a result of this they are not the same size or colour. You could theoretically try and enforce a convention using tests, but it would be difficult, and probably not worthwhile.
可以說,這在真實世界應用程序中也會發生。 “ 主頁” ,“ 文章”和“ 個人資料”視圖均具有橫幅的概念。 橫幅在每個視圖中都是不同的,但大概是一個一致且可識別的視覺元素(實際上,它是視圖的標題/標題)。 視圖不共享這些橫幅的任何代碼,因此,它們的大小或顏色都不相同。 從理論上講,您可以嘗試使用測試來強制執行約定,但是這很困難,而且可能不值得。
輔助功能 (Helper functions)
Another possibility is for child views to be responsible for keeping shared elements consistent, but by using some helper functions. This is definitely a step forward, and is probably the most common solution I see in the wild. The functions can go in the same file and be next to each other. This makes it easier to see that they are related and are representing the same visual element, and easier to make them consistent.
子視圖的另一種可能性是負責使共享元素保持一致,但是要使用一些輔助函數。 這絕對是向前的一步,可能是我在野外看到的最常見的解決方案。 這些功能可以放在同一文件中,并且可以彼此相鄰。 這使得更容易看到它們是相關的并且代表相同的視覺元素,并且更容易使它們保持一致。
However, there are still some drawbacks. The main one is that the child views have to know to use the helper functions, and there is nothing enforcing this. This isn't a huge deal when you only have one shared element and one function to call, but as applications get bigger, you end up with a combinatorial explosion of differences in the shared visual elements. Most people tame this by providing a number of small, focused functions for the various differences. Then the child view has to know about all these functions, and how to compose them, and there no help from the compiler.
但是,仍然存在一些缺點。 主要的一點是子視圖必須知道如何使用幫助器功能,并且沒有什么強制執行此功能。 當您只有一個共享元素和一個函數要調用時,這并不是什么大問題,但是隨著應用程序變得越來越大,您最終將共享視覺元素之間的差異組合起來爆炸。 大多數人通過為各種差異提供一些小的,集中的功能來馴服這一點。 然后,子視圖必須了解所有這些功能以及如何編寫它們,并且編譯器沒有任何幫助。
Again, this arguably occurs in the Real World App: for example in this part of the Profile.view function, which needs to know how to use the viewTabs
, Feed.viewArticles
and Feed.viewPagination
helper functions, and what Html they need to be contained in.
同樣,這可以說是發生在Real World App中:例如,在Profile.view函數的這一部分中 ,它需要知道如何使用viewTabs
, Feed.viewArticles
和Feed.viewPagination
幫助器函數,以及它們需要使用的viewTabs
Feed.viewArticles
包含在。
使用主視圖類型縮放 (Scaling with Master View Types)
In order to overcome these problems, I propose using a Type
to define your site structure (I rather pompously call this a "Master View Type"). Child views then return this type, and the master view takes it as a parameter and returns the html.
為了克服這些問題,我建議使用一種Type
來定義您的站點結構(我相當稱呼它為“主視圖類型”)。 然后,子視圖返回此類型,而主視圖則將其作為參數并返回html。
For the Real World App examples we have been looking at, the Master View Type is below (Viewer
is the person viewing the page in the Real World App). You could arguably have more general banner types here, such as AvatarBanner, or even IconBanner (instead of ViewerBanner) depending on your domain.
對于我們一直在查看的Real World App示例,下面是Master View Type( Viewer
是在Real World App中查看頁面的人)。 可以說,根據您的域的不同,這里可能有更通用的橫幅類型,例如AvatarBanner或什至IconBanner(而不是ViewerBanner)。
type alias Page ={ activeNavBarLink: NavBarLink, banner: Banner, body: Html Msg}type Banner =TextBanner TextBannerProperties| ViewerBanner Viewer| ArticleBanner Viewer ArticlePreviewtype NavBarLink =NavBarLink NavBarLinkProperties
To demonstrate this, I have create a repository with just the Header and Banner parts of the Real World App and then created a new repository after refactoring to use a ?Master Page Type, NavBarLink Type and Banner Type. You can peruse the code to get a feel for how it works.
為了演示這一點,我創建了一個僅包含Real World App的Header和Banner部分的存儲庫,然后在重構后使用Master Page Type , NavBarLink Type和Banner Type創建了一個新的存儲庫。 您可以細讀代碼以了解其工作原理。
To my mind, using a Master Page Type has the following benefits:
我認為,使用母版頁類型具有以下好處:
- Writing the master view code is easier 編寫主視圖代碼更容易
- Writing the child view code is easier 編寫子視圖代碼更容易
- Communication and understanding are improved, as UI concepts now have names 交流和理解得到改善,因為UI概念現在有了名稱
- Theming / redesigning a site is a lot easier 主題化/重新設計網站要容易得多
- Elm packages can provide UI templates Elm包可以提供UI模板
The master view can precisely define what it will accept / support via the types, with union types and opaque types. Non supported combinations can be made unrepresentable or uncreatable.
主視圖可以通過聯合類型和不透明類型通過類型精確定義它將接受/支持的內容。 不受支持的組合可能無法顯示或無法創建。
In my example repository the NavBarLink type is opaque, so it is only possible to create supported NavBarLinks (home
, article
and viewer
). In a similar way Banner is a union type, which means that only supported variants can be represented.
在我的示例存儲庫中, NavBarLink類型是opaque ,因此只能創建受支持的NavBarLinks( home
, article
和viewer
)。 以類似的方式Banner是聯合類型 ,這意味著只能表示受支持的變體。
It would be possible for a programmer to simply change these files, but a proficient programmer would recognise the patterns and follow them. If this isn't enough and you are feeling paranoid, then you can require stricter code review on such files, potentially taking advantage of CODEOWNERS functionality on GitHub and GitLab. In the extreme you can ?provide the modules via an elm package, and restrict push access to the underlying repository.
程序員可以簡單地更改這些文件,但是精通的程序員會識別并遵循這些模式。 如果這還不夠,您會感到偏執,那么您可能需要對此類文件進行更嚴格的代碼審查,從而有可能利用GitHub和GitLab上的CODEOWNERS功能。 在極端情況下,您可以通過elm包提供模塊,并限制對基礎存儲庫的推送訪問。
Child views don't have to do anything more than create an instance of the types. The helper functions all return types, so it's easy to see which functions can be used in a particular context, and is impossible to use functions in the wrong context. For example, if a function returns a HeaderBarLink
, it is impossible to mistakenly use this function to create a link in the FooterBar
, or elsewhere on the page. Child views can also leave some of the complexity to the master view. For example, the child view can define a list of options to choose from, and the master view can render this using buttons, a drop down list or an autocomplete list, depending on the number of options.
子視圖除了創建類型的實例外,無需執行其他任何操作。 輔助函數將所有返回類型用作函數,因此很容易看出可以在特定上下文中使用哪些函數,并且不可能在錯誤的上下文中使用函數。 例如,如果一個函數返回HeaderBarLink
,則不可能錯誤地使用此函數在FooterBar
或頁面的其他位置創建鏈接。 子視圖也可以將某些復雜性留給主視圖。 例如,子視圖可以定義一個選項列表,主視圖可以根據選項的數量使用按鈕,下拉列表或自動完成列表來呈現。
The master page type also provides names for UI concepts, which can then be discussed. For example, a designer could say "Let's move the NavBarLinks to the left hand side", and everybody would know what they meant. A product owner could say "Let's create a new page with an IconBanner, and we'll use the current weather api for the icon" and again, everybody would know what they mean. You can look at this excellent thoughtworks article for more details of this.
母版頁類型還提供UI概念的名稱,然后可以對其進行討論。 例如,設計師可以說“讓NavBarLinks移到左側”,每個人都會知道它們的意思。 產品負責人可能會說:“讓我們用IconBanner創建一個新頁面,然后我們將使用當前的天氣api作為圖標”,同樣,每個人都會知道它們的含義。 您可以查看這篇出色的Thoughtworks文章,以獲取更多詳細信息。
Since the responsibility for turning the Master View Type in to html is all in the same place, it is easy to make drastic changes to the look and feel of a website, and to do theming. These changes and themes can alter the Css and the Html, which is something that the normal theming techniques just can't do. Pragmatically, your Master View Type will often have a body: Html Msg
property (to allow child views complete flexibility on the child specific parts of the page) so there would still be some sprawling code to fix up, but it will definitely be a lot easier.
由于將“主視圖類型”轉換為html的責任都在同一個地方,因此很容易對網站的外觀和風格進行重大更改并進行主題化。 這些更改和主題可能會更改Css 和Html ,這是常規主題技術無法做到的。 實用上,您的“主視圖類型”通常會有一個body: Html Msg
屬性(允許子視圖在頁面的子特定部分上具有完全的靈活性),因此仍然會有一些龐大的代碼需要修復,但是肯定會有很多更輕松。
Finally, it opens up possibility of providing ready made themes and site layouts as packages. This would allow you to just do the following to get a working app, complete with layout and styling:
最后,它提供了將現成的主題和站點布局作為軟件包提供的可能性。 這將使您只需執行以下操作即可獲得可運行的應用程序,包括布局和樣式:
create-elm-app
create-elm-app
elm install elm-bootstrap-starter-template
elm install elm-bootstrap-starter-template
- Write some code to create the Master Page Type 編寫一些代碼來創建母版頁類型
elm-app start
elm-app start
Companies could create packages like these to ensure a consistent look and feel across their applications. Open source designs and layouts could emerge and become commonplace, similar to the way that Bootstrap has revolutionised html and css design. Developers with limited design skills (like me) could concentrate on the the bits they are best at (the logic), but still produce produce elegant websites using these packages.
公司可以創建這樣的軟件包,以確保整個應用程序的外觀一致。 開源設計和布局可能會出現并變得司空見慣,類似于Bootstrap徹底改變了html和css設計的方式。 設計技能有限的開發人員(如我)可以專注于他們最擅長的部分(邏輯上),但仍可以使用這些軟件包來生成美觀的網站。
To demonstrate this I have created a bootstrap starter master view package. It mimics the layout and design of the bootstrap starter template. I have then used this package in a demo elm application. You can browse the demo application to see how it looks, and view the source to see how it works.
為了演示這一點,我創建了一個bootstrap starter主視圖包 。 它模仿了引導程序入門模板的布局和設計。 然后,我在演示elm應用程序中使用了此軟件包。 您可以瀏覽演示應用程序以查看其外觀,并查看源代碼以查看其工作方式。
All these advantages come at a small to negative cost. There is a little more code for the new types, but some duplication is removed. You can view the source of the Real World App repositories from before and after refactoring to use a Master Page Type for the full details.
所有這些優點付出的代價很小或為負。 新類型還有更多代碼,但是刪除了一些重復項。 您可以在重構 前后查看“真實世界”應用程序存儲庫的源, 以使用母版頁類型獲取完整的詳細信息。
結論 (Conclusions)
Master View Types bring a lot of benefits (view code is easier to write and maintain, UI concepts are named and UI packages are possible) for little or no cost. They should improve the code of any Elm application that has issues around enforcing consistency (while allowing flexibility) in their view code, which in my experience is most medium and large applications.
主視圖類型帶來了很多好處(視圖代碼更易于編寫和維護,命名UI概念并且可以使用UI包),而幾乎沒有成本。 他們應該改進任何Elm應用程序的代碼,這些應用程序在其視圖代碼中存在圍繞加強一致性(同時允許靈活性)的問題,據我的經驗,這是大多數中型和大型應用程序。
翻譯自: https://www.freecodecamp.org/news/scaling-elm-views-with-master-view-types/
blender視圖縮放