# Personal opinions about best practices for Panel + HoloViews

**URL:** <https://discourse.holoviz.org/t/personal-opinions-about-best-practices-for-panel-holoviews/6789>\
**Category:** Showcase\
**Tags:** panel, hvplot\
**Created:** [January 28, 2024, 5:54am UTC](https://discourse.holoviz.org/t/personal-opinions-about-best-practices-for-panel-holoviews/6789 "2024-01-28T05:54:11Z")\
**Posts on this page:** 1\
**Showing post:** 2

<div class="post-metadata">

**Author:** ![ahuang11](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/ahuang11/32/4947_2.png) [@ahuang11](https://discourse.holoviz.org/u/ahuang11)\
**Post date:** [January 28, 2024, 6:01am UTC](https://discourse.holoviz.org/t/personal-opinions-about-best-practices-for-panel-holoviews/6789/2 "2024-01-28T06:01:13Z")

</div>

A more coherent version by ChatGPT  
“”"  
After completing the development of what I consider one of my most refined applications yet ([Year vs Climatology - a Hugging Face Space by ahuang11](https://huggingface.co/spaces/ahuang11/year-vs-climatology)), I realized it encompasses numerous examples of best practices, mostly drawn from my experience using HoloViz. In a spontaneous decision, I decided to compile a somewhat unpolished brain dump of these practices:

- Instead of inheriting from `param.Parameterized`, opting for inheritance from [`pn.viewable.Viewer`](https://huggingface.co/spaces/ahuang11/year-vs-climatology/blob/main/app.py#L167) allows direct invocation of the class, resembling a native Panel object. This eliminates the need for calling a method like `ClimateApp().view().servable()`.
- To ensure sliders only trigger callbacks upon mouse-up, set [`throttled=True`](https://huggingface.co/spaces/ahuang11/year-vs-climatology/blob/main/app.py#L13).
- Start by instantiating the [initial layout](https://huggingface.co/spaces/ahuang11/year-vs-climatology/blob/main/app.py#L184-L202) with placeholder `pn.Columns` in ` __init__ `, then populate it later in `onload`.
- Enhance app responsiveness by employing [`onload`](https://huggingface.co/spaces/ahuang11/year-vs-climatology/blob/main/app.py#L203-L212) to prevent webpage hang-ups during slow loading processes. Users can immediately observe a loading indicator upon visiting, signaling ongoing processing.
- Manage loading states effectively by encapsulating widget activation within a [`try/finally` block](https://huggingface.co/spaces/ahuang11/year-vs-climatology/blob/main/app.py#L206-L212). This ensures widgets are always reactivated upon completion or in the event of errors.
- Utilize `pn.Param` or [`from_param` classmethod](https://huggingface.co/spaces/ahuang11/year-vs-climatology/blob/main/app.py#L226-L228) for converting class parameters to widgets, with the latter particularly useful for handling nested dictionaries.
- Renaming widget names can be achieved using [`label`](https://huggingface.co/spaces/ahuang11/year-vs-climatology/blob/main/app.py#L174) when utilizing `pn.Param` or `from_param`.
- Ensure proper param watching/binding by using [`self.param.NAME_OF_PARAM`](https://huggingface.co/spaces/ahuang11/year-vs-climatology/blob/main/app.py#L266-L269) instead of `self.NAME_OF_PARAM`, noting the additional `.param.`.
- Optimize runtime and reduce flickers by updating [`object` and `value`](https://huggingface.co/spaces/ahuang11/year-vs-climatology/blob/main/app.py#L264) on pre-initialized placeholders instead of recreating the panel object every time `pn.bind` runs.
- Preserve plot zoom ranges during updates by wrapping [`hv.DynamicMap` with `pn.bind`](https://huggingface.co/spaces/ahuang11/year-vs-climatology/blob/main/app.py#L276-L285). This prevents the plot from resetting zoom, although some bugs may necessitate workarounds for issues like title/ylabel updating.
- Enhance app speed using [`@pn.cache`](https://huggingface.co/spaces/ahuang11/year-vs-climatology/blob/main/app.py#L339), but remember that `pn.cache` activation depends on input kwargs.
- Employ [`pn.depends` with `watch=True`](https://huggingface.co/spaces/ahuang11/year-vs-climatology/blob/main/app.py#L352) when a method doesn’t return anything.
- Utilize a template’s [`modal` (pop-up container)](https://huggingface.co/spaces/ahuang11/year-vs-climatology/blob/main/app.py#L225) to optimize screen estate if unsure where else to place content.
- Bind to HoloViews streams, noting similarities and differences between [`hv.DynamicMap streams`](https://huggingface.co/spaces/ahuang11/year-vs-climatology/blob/main/app.py#L326) and `pn.bind`.
- Prevent text overlapping by setting opposites with [text align and baseline](https://huggingface.co/spaces/ahuang11/year-vs-climatology/blob/main/app.py#L326).

My approach typically involves:

1. Starting with small iterations, gradually building up functionality. The `panel serve app.py --autoreload` command proves handy in this regard.
2. Focusing initially on layout, ensuring the core structure looks correct.
3. Introducing interactivity with `pn.bind` or `pn.depends` once the layout is satisfactory.

I continuously iterate through these steps when implementing new features, beginning with creating placeholder widgets/panes, verifying visual correctness, and finally adding interactivity. If any of these concepts require clarification, feel free to ask!  
“”"

---

_[View the full topic](https://discourse.holoviz.org/t/personal-opinions-about-best-practices-for-panel-holoviews/6789)._
