gamehu 4 هفته پیش
والد
کامیت
d2b1d64227
100فایلهای تغییر یافته به همراه3756 افزوده شده و 0 حذف شده
  1. BIN
      source/.DS_Store
  2. 5 0
      source/README.mdown
  3. 487 0
      source/_data/styles.styl
  4. 9 0
      source/_discarded/AHA.md
  5. 5 0
      source/_discarded/AI的基本概念.md
  6. 5 0
      source/_discarded/PWA-vs-Flutter-1.md
  7. 54 0
      source/_discarded/act-Hooks-二.md
  8. 5 0
      source/_discarded/six-months-learn-a-language-1.md
  9. 8 0
      source/_discarded/前端深似海.md
  10. BIN
      source/_drafts/.DS_Store
  11. BIN
      source/_posts/.DS_Store
  12. BIN
      source/_posts/1 (1).jpg
  13. 122 0
      source/_posts/12-Factors.md
  14. BIN
      source/_posts/12-Factors/attached-resources.png
  15. BIN
      source/_posts/12-Factors/codebase-deploys.png
  16. BIN
      source/_posts/12-Factors/process-types.png
  17. BIN
      source/_posts/12-Factors/release.png
  18. BIN
      source/_posts/2.jpg
  19. 89 0
      source/_posts/2019年开始.md
  20. BIN
      source/_posts/2019年开始/gratisography-421H.jpg
  21. 204 0
      source/_posts/50个LLM面试问题的终极指南.md
  22. 186 0
      source/_posts/75个顶级思维模型与落地工具全景图.md
  23. 205 0
      source/_posts/AHA.md
  24. BIN
      source/_posts/AHA/a.jpg
  25. 66 0
      source/_posts/AI应用-知识库.md
  26. BIN
      source/_posts/AI应用-知识库/llm.png
  27. 91 0
      source/_posts/Agent-Skills-superpowers.md
  28. BIN
      source/_posts/Agent-Skills-superpowers/1.jpg
  29. 139 0
      source/_posts/CMDB.md
  30. BIN
      source/_posts/CMDB/1.jpg
  31. BIN
      source/_posts/CMDB/2.png
  32. BIN
      source/_posts/CMDB/3.png
  33. BIN
      source/_posts/CMDB/4.png
  34. 41 0
      source/_posts/CSS Triggers.md
  35. BIN
      source/_posts/CSS Triggers/css.png
  36. BIN
      source/_posts/CSS Triggers/render.png
  37. 134 0
      source/_posts/Chrome Tools-Sources.md
  38. BIN
      source/_posts/Chrome Tools-Sources/0.png
  39. BIN
      source/_posts/Chrome Tools-Sources/1.jpg
  40. BIN
      source/_posts/Chrome Tools-Sources/10.png
  41. BIN
      source/_posts/Chrome Tools-Sources/Filesystem.gif
  42. BIN
      source/_posts/Chrome Tools-Sources/Inked0_LI.jpg
  43. BIN
      source/_posts/Chrome Tools-Sources/breakpoints.gif
  44. BIN
      source/_posts/Chrome Tools-Sources/debug.png
  45. BIN
      source/_posts/Chrome Tools-Sources/debug03.gif
  46. BIN
      source/_posts/Chrome Tools-Sources/debug04.gif
  47. BIN
      source/_posts/Chrome Tools-Sources/network-overrides.gif
  48. BIN
      source/_posts/Chrome Tools-Sources/point_types.png
  49. BIN
      source/_posts/Chrome Tools-Sources/snippets.gif
  50. BIN
      source/_posts/Chrome Tools-Sources/watch.png
  51. BIN
      source/_posts/Chrome Tools-Sources/xhr.gif
  52. 20 0
      source/_posts/Clean Architecture.md
  53. 53 0
      source/_posts/Code Review.md
  54. BIN
      source/_posts/Code Review/001.png
  55. BIN
      source/_posts/Code Review/002.png
  56. BIN
      source/_posts/Code Review/003.png
  57. BIN
      source/_posts/Code Review/004.png
  58. BIN
      source/_posts/Code Review/005.png
  59. BIN
      source/_posts/Code Review/code_review_hierarchy.png
  60. BIN
      source/_posts/Code Review/cr001.png
  61. 19 0
      source/_posts/DDD-1.md
  62. BIN
      source/_posts/DDD-1/1.png
  63. 28 0
      source/_posts/DevOps实践.md
  64. 161 0
      source/_posts/Docker 一点点.md
  65. BIN
      source/_posts/Docker 一点点/1.png
  66. BIN
      source/_posts/Docker 一点点/architecture.png
  67. BIN
      source/_posts/Docker 一点点/docker-arch1.jpg
  68. 264 0
      source/_posts/ES Module.md
  69. BIN
      source/_posts/ES Module/1.png
  70. BIN
      source/_posts/ES Module/10.png
  71. BIN
      source/_posts/ES Module/11.png
  72. BIN
      source/_posts/ES Module/12.png
  73. BIN
      source/_posts/ES Module/13.png
  74. BIN
      source/_posts/ES Module/14.png
  75. BIN
      source/_posts/ES Module/15.png
  76. BIN
      source/_posts/ES Module/16.png
  77. BIN
      source/_posts/ES Module/2.png
  78. BIN
      source/_posts/ES Module/3.png
  79. BIN
      source/_posts/ES Module/4.png
  80. BIN
      source/_posts/ES Module/5.png
  81. BIN
      source/_posts/ES Module/6.png
  82. BIN
      source/_posts/ES Module/7.png
  83. BIN
      source/_posts/ES Module/8.png
  84. BIN
      source/_posts/ES Module/9.png
  85. 217 0
      source/_posts/ES2020-2021.md
  86. 45 0
      source/_posts/ESLint-no-prototype-builtins.md
  87. 193 0
      source/_posts/ETL复习(1).md
  88. 15 0
      source/_posts/Event-loops.md
  89. 130 0
      source/_posts/GC.md
  90. BIN
      source/_posts/GC/企业微信截图_8b8b911d-8d45-4120-bad0-4aca1e62ccd1.png
  91. 413 0
      source/_posts/Google-Prompt-Engineering.md
  92. 75 0
      source/_posts/GraphQL.md
  93. 268 0
      source/_posts/Gulp.md
  94. BIN
      source/_posts/Gulp/Gulp.png
  95. BIN
      source/_posts/Gulp/a.gif
  96. BIN
      source/_posts/Gulp/b.jpeg
  97. BIN
      source/_posts/Gulp/duplex.png
  98. BIN
      source/_posts/Gulp/gulp01.png
  99. BIN
      source/_posts/Gulp/gulp02.png
  100. BIN
      source/_posts/Gulp/stream.png

BIN
source/.DS_Store


+ 5 - 0
source/README.mdown

@@ -0,0 +1,5 @@
+gamehu's bolg
+
+[www.gamehu.run](http://www.gamehu.run/)
+
+博客备用地址:http://gamehu.github.io/

+ 487 - 0
source/_data/styles.styl

@@ -0,0 +1,487 @@
+.main-inner
+    width 60%
+// 文章块添加阴影
+.post-block
+    margin-top 60px
+    padding 25px
+    box-shadow 0 0 5px rgb(210 210 210)
+// Custom styles.
+.post {
+  margin-bottom: 60px;
+  margin-top: 0;
+  padding: 25px;
+  -moz-box-shadow: 0 0 5px rgba(202, 203, 204, .5);
+  -webkit-box-shadow: 0 0 5px rgba(202, 203, 203, .5);
+}
+// Custom styles.
+code {
+  background: #fbf7f8;
+  color: #ff7600;
+  margin: 2px;
+}
+// 大代码块的自定义样式
+.highlight, pre {
+  border-radius: 3px;
+  margin: 5px 0;
+  padding: 5px;
+}
+.highlight, code, pre {
+  border: 1px solid #d6d6d6;
+}
+
+//全文字体
+body {
+    font-family: 'Noto Serif SC',"PingFang SC","Microsoft YaHei",sans-serif;
+}
+code, pre {
+    font-family: 'Roboto Mono',consolas,Menlo,monospace,"PingFang SC","Microsoft YaHei";
+}
+.post-body[itemprop="articleBody"] p {
+    color: rgb(63, 63, 63);
+    font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;
+    font-size: 14px;
+    letter-spacing: normal;
+}
+// 菜单栏样式
+.header {
+    background: #ffffff !important;
+}
+
+//去除菜单项左边icon
+.menu-item .fa {
+    display: none;
+}
+
+//更改菜单项字体大小
+.menu-item a, .menu-item span.exturl {
+    font-size: 1.025em;
+}
+.menu-item-active a, .menu .menu-item a:hover, .menu .menu-item span.exturl:hover {
+    background: #ffffff;
+    color: #000;
+    font-size: 1.125em;
+}
+
+//去掉网站名上下的横线
+.logo-line-before i, .logo-line-after i {
+    display: none;
+}
+
+//更改网站名字体大小
+.site-title {
+    font-size: 2em;
+}
+// 菜单栏样式结束
+
+//侧边栏样式
+.sidebar {
+    background: #bbbbbb1a;
+    bottom: 0;
+    position: fixed;
+    box-shadow: inset 0 0px 0px #0000;
+    top: 0;
+    z-index: 200;
+}
+
+//目录与站点概览链接样式
+.sidebar-nav li{
+    color: #555;
+    font-size: 1em;
+}
+.sidebar-nav li:hover{
+    color: #222;
+}
+.sidebar-nav li.sidebar-nav-overview {
+    margin-left: 10px;
+}
+.sidebar-nav .sidebar-nav-active {
+    border-bottom-color: #222;
+    color: #222;
+}
+.sidebar-nav .sidebar-nav-active:hover {
+    border-bottom-color: #222;
+    color: #222;
+}
+
+//目录样式
+.post-toc ol a {
+    border-bottom-color: #5550;
+}
+.post-toc .nav .active-current > a {
+    color: #222;
+}
+.post-toc .nav .active > a {
+    border-bottom-color: #222;
+    color: #222;
+}
+.post-toc .nav .active-current > a:hover {
+    color: #222;
+}
+
+//头像样式
+.site-author-image {
+    border: 0px solid #333;
+}
+
+//name字体颜色
+.site-author-name {
+    color: #222;
+}
+//description颜色
+.site-description {
+    color: #222;
+}
+
+//sidebar-item颜色
+.sidebar a, .sidebar span.exturl {
+    border-bottom-color: #2220;
+    color: #222;
+}
+.sidebar a:hover, .sidebar span.exturl:hover {
+    border-bottom-color: #2220;
+    color: #22222282;
+}
+
+//RSS样式
+.feed-link a, .chat a {
+    border: 0px solid #fc6423;
+}
+.feed-link a:hover, .chat a:hover {
+    background: #bbbbbb1a;
+    border: 0px solid #fc6423;
+    color: #222;
+}
+.fa-feed:before, .fa-rss:before {
+    color: #222;
+}
+
+//社交链接样式
+.links-of-author a::before, .links-of-author span.exturl::before {
+    display: none;
+}
+
+//展开按钮
+.toggle .toggle-line {
+    background: #222;
+    height: 3px;
+}
+.sidebar-toggle {
+    background: #bbb0;
+    height: 20px;
+    width: 25px;
+}
+
+//返回顶部按钮
+.back-to-top {
+    background: #2220;
+        color: #222;
+}
+//侧边栏样式结束
+
+//文章块添加阴影
+.post-block{
+   margin-top: 60px;
+   margin-bottom: 60px;
+   border-radius: 20px; //文章背景设置圆角
+   padding: 30px 60px 30px 60px;
+   background:rgba(255,255,255,0.5) none repeat scroll !important; //添加透明效果
+//    -webkit-box-shadow: 0 0 15px rgba(202, 203, 203, .8); //文章块阴影
+//    -moz-box-shadow: 0 0 15px rgba(202, 203, 204, .8);
+}
+
+//调节文章宽度
+.main-inner {
+    // width: 65%;
+}
+
+//调整子标题文本大小
+.site-subtitle {
+    font-size: 1em;
+}
+
+//加入背景图片
+//body { 
+//	background: url(/images/background.jpg)
+//	background-repeat: no-repeat;
+//    background-attachment:fixed;
+//    background-position:50% 50%;
+//}
+	
+//调整文章块底部空白大小
+.post-eof {
+    margin: 20px auto 20px;
+}
+
+//调整按钮透明度
+.btn {
+    background: rgba(255,255,255,0);
+}
+
+// 重点文字样式1 - 黄色背景标注
+.highlight-text {
+  background-color: #fff566;
+  padding: 2px 5px;
+  border-radius: 3px;
+}
+
+// 重点文字样式2 - 波浪下划线
+.wavy-underline {
+  text-decoration: wavy underline #ff3333;
+}
+
+// 重点文字样式3 - 渐变色文字
+.gradient-text {
+  background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
+  -webkit-background-clip: text;
+  color: transparent;
+  font-weight: bold;
+}
+
+// 重点文字样式4 - 阴影效果
+.shadow-text {
+  text-shadow: 2px 2px 4px rgba(0,0,0,0.2);
+}
+
+// 重点文字样式5 - 边框包围
+.border-text {
+  border: 2px solid #1890ff;
+  padding: 0 5px;
+  border-radius: 4px;
+}
+@keyframes highlight {
+    0% { background-color: #fffae6; }
+    50% { background-color: #fff5cc; }
+    100% { background-color: #fffae6; }
+}
+.animated-highlight {
+    animation: highlight 2s infinite;
+    padding: 10px;
+    border-radius: 5px;
+    font-weight: bold;
+}
+.warning {
+    color: #d9534f; /* 红色字体 */
+    font-weight: bold;
+}
+.warning:before {
+    content: "⚠️"; /* 警告符号 */
+    margin-right: 8px;
+}
+.important-note {
+    border-left: 4px solid #007BFF; /* 蓝色强调 */
+    background-color: #f9f9f9; /* 浅灰背景 */
+    padding: 10px 15px;
+    font-style: italic;
+}
+.card {
+    background-color: #e7f3fe; /* 浅蓝背景 */
+    border: 1px solid #b3d8ff; /* 蓝色边框 */
+    padding: 15px;
+    border-radius: 8px;
+    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
+    font-size: 1rem;
+}
+/* 标签容器 */
+.tag-container {
+  margin-top: 10px;
+  display: flex;
+  flex-wrap: wrap;
+  align-items: center;
+  justify-content: flex-start;
+  margin-bottom: 20px;
+  gap: 5px;
+}
+
+/* 主标签样式 */
+.main-tag {
+  font-size: 11px;
+  font-weight: bold;
+  background: linear-gradient(45deg, #ff416c, #ff4b2b);
+  color: white;
+  padding: 2px 5px;
+  border-radius: 4px;
+  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
+}
+
+/* 次要标签样式 */
+.sub-tag {
+  font-size: 10px;
+  font-weight: 400;
+  background: linear-gradient(45deg, #1fa2ff, #12d8fa);
+  color: white;
+  padding: 2px 5px;
+  border-radius: 4px;
+  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
+}
+.ai-tag {
+      position: relative;
+      display: inline-block;
+      padding: 0px 9px;
+      font-size: 12px;
+      color: white;
+      background: linear-gradient(135deg, #6366F1, #8B5CF6);
+      border-radius: 6px;
+      box-shadow: 0 4px 15px rgba(99, 102, 241, 0.4);
+      overflow: hidden;
+      transition: all 0.3s ease;
+    }
+    
+    .ai-tag::before {
+      content: "";
+      position: absolute;
+      top: -50%;
+      left: -50%;
+      width: 200%;
+      height: 200%;
+      background: linear-gradient(45deg, 
+        rgba(255, 255, 255, 0) 0%, 
+        rgba(255, 255, 255, 0.25) 50%, 
+        rgba(255, 255, 255, 0) 100%);
+      transform: rotate(45deg);
+      animation: shine 3s infinite linear;
+    }
+    
+    .ai-tag:hover {
+      transform: translateY(-3px);
+      box-shadow: 0 6px 20px rgba(99, 102, 241, 0.6);
+    }
+    
+    @keyframes shine {
+      0% {
+        left: -100%;
+        top: -100%;
+      }
+      100% {
+        left: 100%;
+        top: 100%;
+      }
+    }
+    
+    /* 闪烁动画效果 */
+    @keyframes pulse {
+      0%, 100% {
+        opacity: 1;
+        text-shadow: 0 0 0 rgba(255, 255, 255, 0);
+        transform: scale(1);
+      }
+      50% {
+        opacity: 0.9;
+        text-shadow: 0 0 5px rgba(255, 255, 255, 0.3);
+        transform: scale(1.02);
+      }
+    }
+    
+    .ai-tag .blink {
+      animation: pulse 2s infinite ease-in-out;
+      display: inline-block;
+    }
+
+/* 引言样式 */
+.article-quote {
+  position: relative;
+  margin: 2em 0;
+  padding: 1.5em 2em;
+  background: #f8f9fa;
+  border-left: 4px solid #6b90da;
+  border-radius: 3px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.article-quote::before {
+  content: '"';
+  position: absolute;
+  top: 10px;
+  left: 10px;
+  font-size: 3em;
+  color: #6b90da;
+  opacity: 0.2;
+}
+
+/* 正文分割样式 */
+.content-divider {
+  margin: 2em 0;
+  text-align: center;
+  overflow: hidden;
+}
+
+.content-divider::before {
+  content: "✧";
+  color: #6b90da;
+  margin: 0 0.5em;
+}
+
+.content-divider::after {
+  content: "✧";
+  color: #6b90da;
+  margin: 0 0.5em;
+}
+/* 1. 动态渐变分隔线 */
+.divider-gradient {
+  height: 3px;
+  background: linear-gradient(90deg, #12c2e9, #c471ed, #f64f59);
+  margin: 2em 0;
+  background-size: 200% 100%;
+  animation: gradient-move 3s infinite linear;
+}
+
+@keyframes gradient-move {
+  0% { background-position: 0% 50%; }
+  100% { background-position: 200% 50%; }
+}
+
+/* 2. 波浪分隔线 */
+.divider-wave {
+  height: 60px;
+  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 120' preserveAspectRatio='none'%3E%3Cpath d='M321.39,56.44c58-10.79,114.16-30.13,172-41.86,82.39-16.72,168.19-17.73,250.45-.39C823.78,31,906.67,72,985.66,92.83c70.05,18.48,146.53,26.09,214.34,3V0H0V27.35A600.21,600.21,0,0,0,321.39,56.44Z' fill='%23f3f4f6'/%3E%3C/path%3E%3C/svg%3E");
+  background-size: cover;
+  margin: 2em 0;
+}
+
+/* 3. 科技感分隔线 */
+.divider-tech {
+  position: relative;
+  height: 2px;
+  background: #000;
+  margin: 2em 0;
+  overflow: hidden;
+}
+
+.divider-tech::before {
+  content: '';
+  position: absolute;
+  top: 0;
+  left: 0;
+  height: 100%;
+  width: 50%;
+  background: linear-gradient(90deg, transparent, #00ff4c);
+  animation: tech-line 2s infinite;
+}
+
+@keyframes tech-line {
+  0% { transform: translateX(-200%); }
+  100% { transform: translateX(400%); }
+}
+
+/* 4. 星空分隔线 */
+.divider-stars {
+  height: 3px;
+  background: #000;
+  margin: 2em 0;
+  position: relative;
+  overflow: hidden;
+}
+
+.divider-stars::after {
+  content: '★ ★ ★';
+  position: absolute;
+  top: -14px;
+  left: 50%;
+  transform: translateX(-50%);
+  color: #ffd700;
+  animation: twinkle 1.5s infinite;
+}
+
+@keyframes twinkle {
+  0%, 100% { opacity: 1; }
+  50% { opacity: 0.3; }
+}

+ 9 - 0
source/_discarded/AHA.md

@@ -0,0 +1,9 @@
+title: AHA
+author: Gamehu
+tags:
+  - AHA
+categories:
+  - 编程
+date: 2020-11-24 14:56:00
+---
+https://kentcdodds.com/blog/aha-programming

+ 5 - 0
source/_discarded/AI的基本概念.md

@@ -0,0 +1,5 @@
+title: what is AI
+author: Gamehu
+date: 2025-03-14 23:31:13
+tags:
+---

+ 5 - 0
source/_discarded/PWA-vs-Flutter-1.md

@@ -0,0 +1,5 @@
+title: PWA vs Flutter
+author: Gamehu
+date: 2021-07-26 17:56:12
+tags:
+---

+ 54 - 0
source/_discarded/act-Hooks-二.md

@@ -0,0 +1,54 @@
+title: React Hooks(二)
+author: Gamehu
+tags:
+  - React
+categories:
+  - 前端
+date: 2021-05-21 09:45:00
+---
+Allow me to preface this answer by stating that all of these hooks are very rarely used. 99% of the time, you won't need these. They are only meant to cover some rare corner-case scenarios.
+
+useImperativeHandle
+Usually when you use useRef you are given the instance value of the component the ref is attached to. This allows you to interact with the DOM element directly.
+
+useImperativeHandle is very similar, but it lets you do two things:
+
+It gives you control over the value that is returned. Instead of returning the instance element, you explicitly state what the return value will be (see snippet below).
+It allows you to replace native functions (such as blur, focus, etc) with functions of your own, thus allowing side-effects to the normal behavior, or a different behavior altogether. Though, you can call the function whatever you like.
+There could be many reasons you want might to do either of the above; you might not want to expose native properties to the parent or maybe you want to change the behavior of a native function. There could be many reasons. However, useImperativeHandle is rarely used.
+
+useImperativeHandle customizes the instance value that is exposed to parent components when using ref
+
+Example
+
+In this example, the value we'll get from the ref will only contain the function blur which we declared in our useImperativeHandle. It will not contain any other properties (I am logging the value to demonstrate this). The function itself is also "customized" to behave differently than what you'd normally expect. Here, it sets document.title and blurs the input when blur is invoked.
+
+Show code snippet
+
+useLayoutEffect
+While similar to some extent to useEffect(), it differs in that it will run after React has committed updates to the DOM. Used in rare cases when you need to calculate the distance between elements after an update or do other post-update calculations / side-effects.
+
+The signature is identical to useEffect, but it fires synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside useLayoutEffect will be flushed synchronously, before the browser has a chance to paint.
+
+Example
+
+Suppose you have a absolutely positioned element whose height might vary and you want to position another div beneath it. You could use getBoundingCLientRect() to calculate the parent's height and top properties and then just apply those to the top property of the child.
+
+Here you would want to use useLayoutEffect rather than useEffect. See why in the examples below:
+
+With useEffect: (notice the jumpy behavior)
+
+Show code snippet
+
+With useLayoutEffect:
+
+Show code snippet
+
+useDebugValue
+Sometimes you might want to debug certain values or properties, but doing so might require expensive operations which might impact performance.
+
+useDebugValue is only called when the React DevTools are open and the related hook is inspected, preventing any impact on performance.
+
+useDebugValue can be used to display a label for custom hooks in React DevTools.
+
+I have personally never used this hook though. Maybe someone in the comments can give some insight with a good example.

+ 5 - 0
source/_discarded/six-months-learn-a-language-1.md

@@ -0,0 +1,5 @@
+title: six months learn a language
+author: Gamehu
+date: 2022-08-17 11:12:32
+tags:
+---

+ 8 - 0
source/_discarded/前端深似海.md

@@ -0,0 +1,8 @@
+title: 前端深似海
+author: Gamehu
+tags:
+  - 总结
+categories:
+  - 前端
+date: 2021-04-26 10:58:00
+---

BIN
source/_drafts/.DS_Store


BIN
source/_posts/.DS_Store


BIN
source/_posts/1 (1).jpg


+ 122 - 0
source/_posts/12-Factors.md

@@ -0,0 +1,122 @@
+title: 12-Factors
+author: Gamehu
+tags:
+  - 12-Factors
+categories:
+  - 学习
+date: 2018-07-04 12:05:00
+---
+
+**背景**
+
+现公司是传统的ToB业务公司,现在要新开一条产品线,因为公司的之前的产品已经10年了,因为技术等的限制,无法应对现在的快速迭代,公司高层想用现在流行的玩法,寻求突破,刚好之前那家公司的leader,支付宝出来的刚从公司离职,他和事业部的总经理是高中同学,所以瞌睡遇到枕头,就找到他来领头做个事,事业部研发中心在天津,他想做这个事必须得带几个自己信得过并且好用的人(是滴,我很好用),所以我和另外一个同事就通过他的内推去了天津(我是对现在的公司及其失望),那番场景那真就是,新老两派之间充满爱意的碰撞,我们抛弃了之前事业部的所有技术积累,全部从0开始。
+
+这篇文章讲的就是在开垦一个后端脚手架的过程中发现了12-Factors,其实很早以前就听过12-Factors,这次逮着机会好好了解下,刚好最近看jimmysong翻译的《迁移到云原生应用架构》,里面提到了12-Factors,这套理论看来是没过时的,借机学习学习。
+
+**I. 基准代码**
+
+一份基准代码(Codebase),多份部署(deploy)
+
+我们项目是采用类似git flow的方式来管理代码,首先每个应用肯定只有一份基准代码(master),不管是新功能的开发、bugfix、hostfix、release、tag等最终都是基于master的。这样就保证了所有部署的基准代码相同,但每份部署可以使用其不同的版本
+
+{% asset_img codebase-deploys.png 来源于12factor.net  %}
+
+**II. 依赖**
+
+显式声明依赖关系( dependency )
+
+每个应用都有自己的依赖清单,前端是package.json,后端是pom.xml。每个应用都会显示的列出依赖。
+
+**III. 配置**
+
+在环境中存储配置。
+
+每个应用都有自己的配置文件(yaml),针对不同的场景有不同的配置,发布、预发布、测试等。杜绝把配置写死在代码里的情况发生。
+
+**IV. 后端服务**
+
+把后端服务(backing services)当作附加资源
+
+数据库、消息队列、数据中心等都是作为基础设施存在的,每个应用是与这些组件都是松耦合。不足是现有的客户场景对可能只能做到逻辑上的隔离,比如数据库虽然逻辑上和应用是隔离的但是物理上可能在一个主机上,因为客户现场可能就跟我们提供几台机器。
+
+{% asset_img attached-resources.png 来源于12factor.net  %}
+
+**
+V. 构建,发布,运行**
+
+严格分离构建和运行。
+
+项目采用的是阿里云的ci/cd方案,构建、发布、运行都是分离的。每个版本对应唯一ID。
+
+{% asset_img release.png 来源于12factor.net  %}
+
+**VI. 进程**
+
+以一个或多个无状态进程运行应用
+
+12-Factor 应用的进程必须无状态且 无共享 。 任何需要持久化的数据都要存储在 后端服务 内,比如数据库。
+
+项目中,进程中无共享,权限、session等都存到redis中。
+
+**VII. 端口绑定**
+
+通过端口绑定(Port binding)来提供服务
+
+这点没什么说的,项目所有的应用提供服务都是通过端口与应用绑定的。
+
+**VIII. 并发**
+
+通过进程模型进行扩展。
+
+这一点没做好,后端采用的java语言,都知道java是典型的线程模式。所以只能给应用分配相应的资源,让其能纵向扩展,但其实效果不是很好。当然我们有比较简单的方式可以使其进行横向扩展,即每个应用部署多实例的方式进行横向扩展,不过目前没有实践。后续会完善。
+
+{% asset_img process-types.png 来源于12factor.net  %}
+
+**IX. 易处理**
+
+快速启动和优雅终止可最大化健壮性。
+
+该原则要求应用可以瞬间启动和停止,因为这将有利于应用快速进行横向扩展和变更或者故障后的重新部署,而这两者都是程序健壮性的体现。
+
+快速启动是做到了,但是优雅的终止还带完善。
+
+**X. 开发环境与线上环境等价**
+
+尽可能的保持开发,预发布,线上环境相同。
+
+我们的发布部署统一走的阿里云效的流水线,流水线的配置除了机器不同其他都一样。
+
+**XI. 日志**
+
+把日志当作事件流。
+
+这块没做好,待完善。个人觉得是很有必要的,后期会酌情加上日志处理分析组件。从日志输出到读取,到分析,到加工,到视图一条龙服务。
+
+**XII. 管理进程**
+
+后台管理任务当作一次性进程运行
+
+*官方说明:*
+
+ 开发人员经常希望执行一些管理或维护应用的一次性任务,例如:
+	
+-   运行数据移植
+-   运行一些提交到代码仓库的一次性脚本。
+
+一次性管理进程应该和正常的 常驻进程 使用同样的环境。这些管理进程和任何其他的进程一样使用相同的 代码 和 配置 ,基于某个 发布版本 运行。后台管理代码应该随其他应用程序代码一起发布,从而避免同步问题。
+
+
+>我理解意思就是应用的管理工具应该随产品一起提供,并且管理任务应该从生产环境中运行最新版本的生产代码的机器上执行此任务。换句话说,从与生产相同的环境中运行一次性管理任务。而不要做类似直接对数据库运行更新这种操作,我理解意思应该是有配套的管理工具而且管理工具是与生产环境同步的,如果需要做一些一次性的维护管理任务,比如数据库移植、A/B测试等任务时不要做手动去改数据库这样很容易造成环境搞乱的操作。
+
+这点在我们项目还是比较弱的,0.1阶段基本上没有统一的管理工具,大家都是通过手动改库等操作达到目的。后期会争取做到这一点。
+
+**12-factor 到底好不好,适不适用,我觉得不是绝对的,目前我们遵循这套是因为我们觉得它对我们有指导意义而且是有效的够用的。**
+
+源引:
+{% blockquote 12-Factor https://12factor.net/zh_cn/ https://12factor.net/zh_cn/ %}
+{% endblockquote %}
+
+{% blockquote 12-Factor Apps in Plain English | clearlytech http://www.clearlytech.com/2014/01/04/12-factor-apps-plain-english/ %}
+{% endblockquote %}
+
+`本文引用的内容,如有侵权请联系我删除,给您带来的不便我很抱歉。`

BIN
source/_posts/12-Factors/attached-resources.png


BIN
source/_posts/12-Factors/codebase-deploys.png


BIN
source/_posts/12-Factors/process-types.png


BIN
source/_posts/12-Factors/release.png


BIN
source/_posts/2.jpg


+ 89 - 0
source/_posts/2019年开始.md

@@ -0,0 +1,89 @@
+title: 2019年开始
+author: Gamehu
+tags:
+  - 规划
+categories:
+  - 成长
+date: 2019-02-19 11:02:00
+---
+
+嗯.....19年过了两个月了是时候开始做个19的规划了,为什么一开始没做,因为我相当不专业的忘了...看斗自己都老火,这就体现了我和专业人士的区别,还是比较业余,谁叫我放荡不羁爱浪,需要自我克制一下,所以19规划还是得做。
+
+{% asset_img gratisography-421H.jpg from gratisography %}
+
+
+## ok 2019年我需要这么规划一下 ##
+
+**知识丰富**
+
+*时间分布:地铁上、睡前半小时、上班的午间休息、周末每天2-3小时*
+
+1. 一个季度看2-3本书,根据书的厚薄进行动态调整,内容:技术类(谁叫我时程序员呢)、提升认知类(说起高大上,就是看一些扫盲的)、自个儿国家人文类(你会发现中国人的牛气冲天以及中国文化的博大精深,绝对时认真的)、心理学类(看看自己内心到底有多么黑暗)
+
+
+2. 几个知识付费的课程学完,花钱买教训(知识)。
+
+
+3. 国外的几个网站多逛逛,看英文文档。好歹对得起自己高中唯一一次英文及格的辉煌(而且是在高考)。
+
+
+**提升影响力**
+
+1. 用心经营自己的社交圈,别让自己太独孤求败。
+
+2. 让领导清楚自己在干什么,多和领导进行沟通。
+
+3. 把团队内分享这事做得更好
+
+
+**继续坚持**
+
+
+目标笔记小程序:
+
+1. 小目标定好,每天上班路上做好目标规划以及时间规划。下班回家睡觉前想一想然后回顾一下。
+
+2. 大目标(按月、年)定好,每天看一遍,为其调整为其努力。
+
+番茄土豆APP:
+
+按照番茄土豆的时间节奏进行,注意身体,保持高效。
+
+
+**变得完美**
+
+
+1. 为成为完美的男人而努力,经常对着镜子反思自己的缺点,把缺点改的不那么缺。
+
+2. 养成早起早睡的习惯,嗯 现在已经比之前提前了一个小时起床,赞一个。要继续加油。
+
+3. 雾霾散去,锻炼身体,一周2-3次,一次20-30分钟,根据自己老的程度,动态调整。
+
+4. 治理拖延症(指生活上的,工作上我从不拖延!!!),想到事情了马上做,听到指令后马上做(这条主要是针对媳妇儿的教导)
+
+**休闲清单**
+
+*时间分布:晚上9点半之前、周末3-4小时*
+
+1. 除了学习和工作时间外的休息时间(作为凡人,需要偷懒放松),可供选择的休闲方式:
+
+2. 看电影(嗯,一个月怎么滴也得一场)
+
+3. 网络视频(Running Man、圆桌派、这就是街舞)
+
+4. 听音乐(各种直击灵魂和耳朵的音乐)
+
+5. 偶然性看小说(如果阴差阳错发现有喜欢的,就看一部,下班地铁上会看)
+
+**心愿清单**
+
+
+
+1. 至少给媳妇儿准备一个惊喜,希望她每天都高高兴兴的。
+
+2. 带老婆孩子去海边玩几天(国外)。
+
+3. 双方父母做一个全面体检,根据身体情况配置上对应的保险。
+
+4. 2-3次自驾游。
+

BIN
source/_posts/2019年开始/gratisography-421H.jpg


+ 204 - 0
source/_posts/50个LLM面试问题的终极指南.md

@@ -0,0 +1,204 @@
+title: 50个LLM面试问题的终极指南
+author: Gamehu
+date: 2025-11-17 00:46:52
+tags:
+  - 基础
+categories:
+  - AI
+---
+<div class="tag-container">
+  <span class="ai-tag">AI</span>
+  <span class="sub-tag">Spec-kit</span>
+</div>
+
+# 掌握大型语言模型:50道面试题终极指南
+
+本文基于一篇优秀的Medium文章,解析并提炼了50道经典LLM面试题。我对内容进行了润色和优化,使其更简洁、实用,同时保留了核心知识点。此次版本特别结合了相关图示,帮助你更直观地理解复杂概念。无论你是求职者、面试官,还是AI爱好者,这份指南都能帮你快速掌握LLM的核心概念、机制和应用。
+
+这些问题涵盖了从基础原理到高级技巧的方方面面,每个问题后附带简明解释,帮助你获得“顿悟”时刻。让我们一起来探索吧!
+
+## 1. 什么是分词(Tokenization),为什么它对LLM至关重要?
+分词是将文本分解成更小的单位(如单词、子词或字符)的过程。例如,“artificial”可能被拆分成“art”、“ific”和“ial”。这对LLM至关重要,因为模型处理的是数字而非原始文本。分词能处理多种语言、稀有词汇,并优化词汇表大小,提高计算效率和模型性能。
+
+## 2. Transformer模型中的注意力机制是如何工作的?
+注意力机制允许LLM在生成或解释文本时,权衡序列中不同token的重要性。它通过查询(query)、键(key)和值(value)向量计算相似度分数(如点积)。例如,在“The cat chased the mouse”中,它能将“mouse”与“chased”关联起来,提升上下文理解,使Transformer在NLP任务中表现出色。
+
+
+
+
+## 3. LLM中的上下文窗口是什么,为什么重要?
+上下文窗口是指LLM一次能处理的token数量上限(如32,000个token),它定义了模型的“记忆”范围。更大的窗口能提升如摘要生成的任务连贯性,但会增加计算成本。在实际部署中,平衡窗口大小与效率是关键。
+
+## 4. LoRA和QLoRA在LLM微调中的区别是什么?
+LoRA(Low-Rank Adaptation)通过添加低秩矩阵来高效微调模型,减少内存开销。QLoRA在此基础上引入量化(如4-bit精度),进一步降低内存需求。例如,QLoRA能让70B参数模型在单GPU上微调,适合资源有限的环境。
+
+
+
+
+## 5. 束搜索(Beam Search)如何比贪婪解码(Greedy Decoding)更好地生成文本?
+束搜索在生成文本时保留前k个(例如k=5)最佳序列,探索更多路径,而贪婪解码只选最高概率词。这能产生更连贯的输出,尤其在机器翻译或对话生成中,平衡概率与多样性。
+
+
+
+
+## 6. 温度(Temperature)在控制LLM输出中扮演什么角色?
+温度是一个超参数,用于调整文本生成的随机性。低温度(如0.3)偏好高概率token,输出更可预测;高温度(如1.5)增加多样性。通过设置如0.8,能在创意任务如讲故事中平衡创造力和连贯性。
+
+## 7. 什么是掩码语言建模(Masked Language Modeling),它如何辅助预训练?
+掩码语言建模(MLM)是将序列中随机token隐藏,并训练模型基于上下文预测它们。如BERT模型中使用,这促进双向语言理解,捕捉语义关系,为情感分析或问答等任务打下基础。
+
+
+
+
+## 8. 序列到序列(Seq2Seq)模型是什么,在哪里应用?
+Seq2Seq模型将输入序列转换为输出序列(长度可不同),由编码器处理输入、解码器生成输出。应用包括机器翻译(如英文到西班牙文)、文本摘要和聊天机器人,处理变长输入输出。
+
+## 9. 自回归模型和掩码模型在LLM训练中的区别是什么?
+自回归模型(如GPT)基于先前token顺序预测,擅长生成任务如文本补全。掩码模型(如BERT)使用双向上下文预测掩码token,适合分类等理解任务。训练目标决定了它们在生成 vs. 理解上的优势。
+
+## 10. 什么是嵌入(Embeddings),在LLM中如何初始化?
+嵌入是将token表示为连续空间中的稠密向量,捕捉语义和句法属性。通常随机初始化或用预训练如GloVe,然后在训练中微调。例如,“dog”的嵌入可能在宠物相关任务中演化,提升模型准确性。
+
+## 11. 什么是下一句预测(Next Sentence Prediction),它如何提升LLM?
+下一句预测(NSP)训练模型判断两句是否连续(50%正样本,50%负样本)。如BERT中使用,这改善如对话系统或文档摘要的任务连贯性,通过理解句子关系。
+
+## 12. Top-k和Top-p采样在文本生成中的区别是什么?
+Top-k采样选择前k个最高概率token(如k=20)随机采样,确保控制多样性。Top-p(核采样)选择累积概率超过阈值p(如0.95)的token,更灵活。在创意写作中,Top-p能产生多样且连贯的输出。
+
+## 13. 为什么提示工程(Prompt Engineering)对LLM性能至关重要?
+提示工程是设计输入以引发理想响应的艺术。例如,“用100字总结这篇文章”比模糊指令更有效。在零样本或少样本设置中,它让LLM无需大量微调就能处理翻译或分类任务。
+
+## 14. LLM如何在微调中避免灾难性遗忘(Catastrophic Forgetting)?
+灾难性遗忘是微调抹除先前知识的现象。缓解方法包括:重放(混合旧新数据)、弹性权重整合(保护关键权重)、模块化架构(添加任务特定模块)。这些确保LLM在多任务中保持多功能性。
+
+## 15. 什么是模型蒸馏(Model Distillation),它如何益处LLM?
+模型蒸馏训练“小学生”模型模仿“大老师”模型的输出,使用软概率而非硬标签。这减少内存和计算需求,让模型能在智能手机上部署,同时保留近似性能,适合实时应用。
+
+## 16. LLM如何处理词汇表外(OOV)词?
+LLM使用子词分词如字节对编码(BPE),将OOV词拆分成已知子词。例如,“cryptocurrency”拆成“crypto”和“currency”。这确保处理稀有或新词,增强语言理解和生成鲁棒性。
+
+## 17. Transformer如何优于传统Seq2Seq模型?
+Transformer通过并行处理(自注意力同时处理token)、捕捉长距离依赖、位置编码(保留顺序)来改进。相比RNN的顺序处理,这些提升了可扩展性和如翻译任务的性能。
+
+
+
+
+## 18. 什么是过拟合(Overfitting),在LLM中如何缓解?
+过拟合是模型记忆训练数据但无法泛化。缓解包括:正则化(L1/L2惩罚)、Dropout(随机禁用神经元)、早停(验证性能停滞时停止)。这些确保对未见数据的鲁棒泛化。
+
+## 19. NLP中的生成模型和判别模型有什么区别?
+生成模型(如GPT)建模联合概率,创建新数据如文本。判别模型(如BERT分类)建模条件概率,区分类别如情感分析。生成模型擅长创建,判别模型聚焦准确分类。
+
+## 20. GPT-4与GPT-3在功能和应用上的区别是什么?
+GPT-4超越GPT-3的多模态输入(文本+图像)、更大上下文(25,000 vs. 4,096 token)、更高准确性(减少事实错误)。这扩展了其在视觉问答和复杂对话的应用。
+
+## 21. 什么是位置编码(Positional Encodings),为什么使用?
+位置编码为Transformer输入添加序列顺序信息,因为自注意力无固有顺序。用正弦函数或学习向量,确保如“king”和“crown”基于位置正确解释,关键于翻译任务。
+
+
+
+
+## 22. 什么是多头注意力(Multi-Head Attention),它如何提升LLM?
+多头注意力将查询、键、值拆分成多个子空间,同时关注输入的不同方面。例如,一头关注句法,另一头关注语义。这提升模型捕捉复杂模式的能力。
+
+
+
+
+## 23. Softmax函数在注意力机制中如何应用?
+Softmax将注意力分数规范化成概率分布:在注意力中,将原始相似分数(查询-键点积)转为权重,强调相关token,确保模型聚焦上下文重要部分。
+
+## 24. 点积在自注意力中如何贡献?
+在自注意力中,查询(Q)和键(K)向量的点积计算相似分数:高分表示相关token。尽管高效,但其二次复杂度(O(n²))促使研究稀疏注意力。
+
+## 25. 为什么在语言建模中使用交叉熵损失(Cross-Entropy Loss)?
+交叉熵测量预测与真实token概率的差异:它惩罚错误预测,鼓励准确token选择。在语言建模中,确保模型为正确下一token分配高概率,优化性能。
+
+## 26. LLM中嵌入的梯度如何计算?
+嵌入梯度通过链式法则在反向传播中计算:这些梯度调整嵌入向量以最小化损失,精炼语义表示,提升任务性能。
+
+## 27. Jacobian矩阵在Transformer反向传播中的作用是什么?
+Jacobian矩阵捕捉输出对输入的部分导数。在Transformer中,它帮助计算多维输出的梯度,确保权重和嵌入的准确更新,优化复杂模型。
+
+## 28. 特征值和特征向量如何与降维相关?
+特征向量定义数据主方向,特征值表示方差。在PCA中,选择高特征值的向量减少维度,同时保留大部分方差,便于LLM输入处理。
+
+## 29. 什么是KL散度(KL Divergence),在LLM中如何使用?
+KL散度量化两个概率分布的差异:在LLM中,它评估模型预测与真实分布的接近度,指导微调改善输出质量和数据对齐。
+
+## 30. ReLU函数的导数是什么,为什么重要?
+ReLU函数f(x) = max(0, x)的导数为:1 (x > 0),0 (x ≤ 0)。其稀疏性和非线性防止梯度消失,使ReLU在LLM中高效且广泛使用。
+
+## 31. 链式法则如何应用于LLM中的梯度下降?
+链式法则计算复合函数导数:在梯度下降中,它启用反向传播逐层计算梯度,高效更新参数,最小化深度LLM架构的损失。
+
+## 32. Transformer中注意力分数如何计算?
+注意力分数计算为:缩放点积测量token相关性,Softmax规范化分数,聚焦关键token,提升如摘要的上下文生成。
+
+## 33. Gemini如何优化多模态LLM训练?
+Gemini通过统一架构(结合文本和图像)、高级注意力(提升跨模态学习稳定性)、数据效率(自监督减少标签需求)来优化。更稳定、可扩展于如GPT-4。
+
+## 34. 基础模型有哪些类型?
+基础模型包括:语言模型(BERT、GPT-4用于文本)、视觉模型(ResNet用于图像分类)、生成模型(DALL-E用于内容创建)、多模态模型(CLIP用于文本-图像)。它们利用广泛预训练适用于多样应用。
+
+## 35. PEFT如何缓解灾难性遗忘?
+参数高效微调(PEFT)仅更新小部分参数,冻结其余以保留预训练知识。如LoRA,确保LLM适应新任务而不丢失核心能力,维持跨域性能。
+
+## 36. 检索增强生成(RAG)的步骤是什么?
+RAG包括:检索(用查询嵌入获取相关文档)、排序(按相关性排序)、生成(用检索上下文生成准确响应)。提升如问答的任务事实准确性。
+
+
+
+
+## 37. 专家混合(MoE)如何提升LLM可扩展性?
+MoE用门控函数激活特定专家子网络,减少计算负载。例如,每查询仅用10%参数,让亿级参数模型高效运行,同时保持高性能。
+
+## 38. 思维链(Chain-of-Thought)提示是什么,它如何辅助推理?
+CoT提示引导LLM逐步解决问题,模仿人类推理。例如,在数学问题中分解计算,提升复杂任务如逻辑推理的准确性和可解释性。
+
+
+
+
+## 39. 判别AI和生成AI的区别是什么?
+判别AI(如情感分类器)基于输入特征预测标签,建模条件概率。生成AI(如GPT)创建新数据,建模联合概率,适合文本或图像生成,提供创意灵活性。
+
+## 40. 知识图谱集成如何改善LLM?
+知识图谱提供结构化事实数据,通过减少幻觉(验证事实)、改善推理(利用实体关系)、增强上下文来提升LLM。适用于问答和实体识别。
+
+## 41. 什么是零样本学习(Zero-Shot Learning),LLM如何实现?
+零样本学习让LLM使用预训练通用知识执行未训练任务。例如,提示“将此评论分类为积极或消极”,无需特定数据即可推断情感,展示其多功能性。
+
+## 42. 自适应Softmax如何优化LLM?
+自适应Softmax按频率分组词,减少稀有词计算。降低大词汇表成本,加速训练和推理,同时保持准确性,尤其在资源有限环境中。
+
+## 43. Transformer如何解决梯度消失问题?
+Transformer通过自注意力(避免顺序依赖)、残差连接(直接梯度流)、层规范化(稳定更新)来缓解。与RNN不同,确保深度模型有效训练。
+
+## 44. 什么是少样本学习(Few-Shot Learning),其益处是什么?
+少样本学习让LLM用少量示例执行任务,利用预训练知识。益处包括减少数据需求、快速适应、成本效率,适合利基任务如特定文本分类。
+
+## 45. 如何修复LLM生成偏见或错误输出?
+解决方法:1. 分析模式(识别偏见来源);2. 增强数据(用平衡数据集和去偏技术);3. 微调(用精选数据或对抗方法重训)。改善公平性和准确性。
+
+## 46. Transformer中编码器和解码器的区别是什么?
+编码器将输入序列处理成抽象表示,捕捉上下文。解码器生成输出,使用编码器输出和先前token。在翻译中,编码器理解源语言,解码器产生目标语言,实现有效Seq2Seq任务。
+
+
+
+
+## 47. LLM与传统统计语言模型的区别是什么?
+LLM使用Transformer架构、海量数据集和无监督预训练,而统计模型(如N-gram)依赖简单监督方法。LLM处理长距离依赖、上下文嵌入和多样任务,但需大量计算资源。
+
+## 48. 什么是超参数,为什么重要?
+超参数是预设值,如学习率或批次大小,控制模型训练。它们影响收敛和性能;例如,高学习率可能导致不稳定。调优超参数优化LLM效率和准确性。
+
+## 49. 什么是大型语言模型(LLM)?
+LLM是训练于海量文本语料的AI系统,能理解和生成类人语言。拥有亿级参数,在翻译、摘要和问答中卓越,利用上下文学习广泛适用。
+
+## 50. LLM部署面临哪些挑战?
+挑战包括:资源密集(高计算需求)、偏见(延续训练数据偏见)、可解释性(复杂模型难解释)、隐私(数据安全担忧)。解决这些确保LLM的伦理和有效使用。
+
+
+
+## 参考来源
+
+https://transformers.run/c1/transformer/

+ 186 - 0
source/_posts/75个顶级思维模型与落地工具全景图.md

@@ -0,0 +1,186 @@
+title: 75个顶级思维模型与落地工具全景图
+author: Gamehu
+date: 2025-11-25 21:46:26
+tags:
+  - 思维模型
+categories:
+  - 个人成长
+---
+
+
+# 75个顶级思维模型与落地工具全景图
+
+> **“手中只有锤子的人,看什么问题都像钉子。” —— 查理·芒格**
+
+在商业决策、创业管理和个人成长中,我们常犯的错误不是不够聪明,而是**思维维度的单一**。
+
+所谓的“高手”,往往建立了一个跨学科的**“多元思维模型格栅” (Latticework of Mental Models)**。他们不只懂技术,还懂心理学;不只懂管理,还懂系统动力学。
+
+但知道理论只是第一步,**如何将抽象的“模型”转化为可执行的“动作”?**
+
+本文为您整理了 **8大类、75个核心思维模型**,并一一映射了业界最成熟的**实战方法论与工具**。这不仅是一份认知清单,更是创业者和管理者的**实战核对表**。
+
+---
+
+## 🧠 第一部分:底层逻辑与认知操作系统
+**核心目标:提升思考质量,避免愚蠢的错误。**
+
+这些是思考“思考本身”的模型,是所有决策的基础。
+
+| 序号 | 思维模型 | 核心理念 | ⚔️ 落地方法论/工具 | 实战应用场景 |
+| :--- | :--- | :--- | :--- | :--- |
+| 1 | **第一性原理** (First Principles) | 回归事物最基本的真理,从头推导。 | **5 Whys 分析法** / **苏格拉底提问法** | 颠覆式创新、打破常规流程。 |
+| 2 | **逆向思维** (Inversion) | 先想如何失败,然后避开它。 | **事前验尸 (Pre-mortem)** | 项目启动前的风险排查。 |
+| 3 | **二阶思维** (Second-Order Thinking) | 不只看直接后果,要看后果的后果。 | **决策树** / **影响地图 (Impact Mapping)** | 政策制定、复杂决策推演。 |
+| 4 | **地图非疆域** (Map is not Territory) | 模型只是简化,现实更复杂。 | **现地现物 (Genchi Genbutsu)** | 丰田管理法:亲自去现场看真实情况。 |
+| 5 | **奥卡姆剃刀** (Occam's Razor) | 如无必要,勿增实体。 | **MVP** / **代码重构** | 砍掉冗余流程、简化产品设计。 |
+| 6 | **汉隆剃刀** (Hanlon's Razor) | 能用愚蠢解释的,别用恶意解释。 | **SBI 反馈法** | 沟通时只讲事实(S/B/I),减少情绪内耗。 |
+| 7 | **能力圈** (Circle of Competence) | 知之为知之,不知为不知。 | **能力矩阵** / **外包决策表** | 决定什么自己做,什么必须外包。 |
+| 8 | **概率思维** (Probabilistic Thinking) | 世界是灰度的,用概率下注。 | **期望值计算 (Expected Value)** | 计算 `(赢率x收益) - (输率x成本)`。 |
+| 9 | **贝叶斯更新** (Bayesian Updating) | 随新信息出现,动态调整观点。 | **A/B 测试** | 根据测试数据验证并修正策略。 |
+| 10 | **可证伪性** (Falsifiability) | 科学理论必须容许被证明是错的。 | **假设检验 (Hypothesis Testing)** | 精益创业:设计实验去验证商业假设。 |
+
+---
+
+## ♟️ 第二部分:战略规划与竞争博弈
+**核心目标:找准方向,建立壁垒。**
+
+不要用战术上的勤奋,掩盖战略上的懒惰。
+
+| 序号 | 思维模型 | 核心理念 | ⚔️ 落地方法论/工具 | 实战应用场景 |
+| :--- | :--- | :--- | :--- | :--- |
+| 11 | **护城河** (Economic Moat) | 建立不可复制的竞争优势。 | **VRIO 分析模型** | 评估资源的稀缺性和不可模仿性。 |
+| 12 | **跨越鸿沟** (Crossing the Chasm) | 早期市场到主流市场有巨大断层。 | **STP 营销理论** | 针对不同阶段切换目标用户群。 |
+| 13 | **红海/蓝海** (Red/Blue Ocean) | 避开血腥竞争,创造新需求。 | **战略布局图** / **ERC 动作框架** | 剔除、减少、增加、创造。 |
+| 14 | **不对称战争** (Asymmetric Warfare) | 利用强者的弱点以弱胜强。 | **游击营销 (Guerrilla Marketing)** | 低成本、创意突袭大公司盲区。 |
+| 15 | **破坏性创新** (Disruptive Innovation) | 从低端切入,最终颠覆高端。 | **JTBD (Jobs to be Done)** | 挖掘用户“雇佣”产品的真实任务。 |
+| 16 | **红皇后效应** (Red Queen Effect) | 不进则退,必须比对手跑得更快。 | **标杆管理 (Benchmarking)** | 持续对标行业第一名的数据。 |
+| 17 | **博弈论** (Game Theory) | 你的收益取决于对手的行动。 | **囚徒困境矩阵** / **纳什均衡** | 定价策略、商务谈判分析。 |
+| 18 | **只有偏执狂才能生存** | 时刻警惕战略转折点。 | **PESTEL 分析** | 扫描宏观环境的突变风险。 |
+| 19 | **孙子兵法** (Sun Tzu) | 知己知彼,攻其不备。 | **商业兵棋推演 (Business Wargaming)** | 模拟红蓝军对抗,预演对手反应。 |
+| 20 | **有限/无限博弈** | 有的游戏为了赢,有的为了玩下去。 | **使命愿景价值观 (MVV)** | 确立企业的终极目标。 |
+
+---
+
+## 📈 第三部分:系统动力学与增长
+**核心目标:理解业务如何变大、变乱或崩溃。**
+
+系统不仅仅是零件的堆砌,而是零件之间的关系。
+
+| 序号 | 思维模型 | 核心理念 | ⚔️ 落地方法论/工具 | 实战应用场景 |
+| :--- | :--- | :--- | :--- | :--- |
+| 21 | **复利效应** (Compounding) | 指数级增长的威力。 | **定投策略** / **Wiki 知识库** | 财务积累、团队知识沉淀。 |
+| 22 | **临界质量** (Critical Mass) | 量变引起质变的引爆点。 | **病毒系数 (K-factor) 计算** | 确保 K>1 实现自增长。 |
+| 23 | **网络效应** (Network Effects) | 用户越多,价值越大。 | **梅特卡夫定律** | 平台型产品的估值与增长设计。 |
+| 24 | **飞轮效应** (Flywheel Effect) | 咬合齿轮,一旦转动惯性巨大。 | **增长回路图** | 设计业务闭环(如亚马逊飞轮)。 |
+| 25 | **熵增定律** (Entropy) | 封闭系统必然走向混乱。 | **5S 管理法** / **断舍离** | 整理整顿、定期重构、清除死代码。 |
+| 26 | **反馈循环** (Feedback Loops) | 正反馈导致暴涨,负反馈维持稳定。 | **系统动力学建模** | 识别增强回路与调节回路。 |
+| 27 | **涌现** (Emergence) | 简单的个体汇聚成群体智慧。 | **Scrum / 敏捷开发** | 自组织团队,去中心化管理。 |
+| 28 | **幂律分布** (Power Law) | 极少数人拿走极大部分利益。 | **ABC 分析法** | 重点管理最重要的20%(A类)。 |
+| 29 | **长尾理论** (The Long Tail) | 小众市场的总和匹敌热门市场。 | **SEO 关键词矩阵** | 覆盖大量低频但精准的长尾流量。 |
+| 30 | **制约理论** (Theory of Constraints) | 链条强度取决于最弱的一环。 | **DBR (鼓-缓冲-绳) 系统** | 找到瓶颈,围绕瓶颈排期。 |
+
+---
+
+## 💰 第四部分:财务、经济与资源配置
+**核心目标:算账、搞钱、提升效率。**
+
+商业的本质是价值交换,而财务是商业的语言。
+
+| 序号 | 思维模型 | 核心理念 | ⚔️ 落地方法论/工具 | 实战应用场景 |
+| :--- | :--- | :--- | :--- | :--- |
+| 31 | **机会成本** (Opportunity Cost) | 选择A的成本是放弃了B。 | **艾森豪威尔矩阵 (四象限)** | 放弃“紧急不重要”的事。 |
+| 32 | **沉没成本** (Sunk Cost) | 泼出去的水,别再想了。 | **零基预算法 (ZBB)** | 预算从零算起,不参考历史投入。 |
+| 33 | **边际效用递减** | 投入越多,新增产出越少。 | **边际分析** | 决策是否继续增加投入(如加班)。 |
+| 34 | **安全边际** (Margin of Safety) | 预留缓冲空间应对未知。 | **盈亏平衡分析** | 预留30%以上的现金流缓冲。 |
+| 35 | **单元经济** (Unit Economics) | 单笔交易必须赚钱。 | **LTV / CAC 模型** | 验证商业模式(SaaS标准 > 3)。 |
+| 36 | **套利** (Arbitrage) | 利用信息/价格差获利。 | *(无特定通用管理工具)* | 早期红利捕捉、跨市场交易。 |
+| 37 | **杠杆作用** (Leverage) | 劳动力、资本、代码、媒体。 | **杜邦分析法** | 拆解ROE,看靠什么撬动收益。 |
+| 38 | **现金转换周期** (CCC) | 资金周转速度决定生死。 | **营运资本管理** | 压缩应收账款,延长应付账款。 |
+| 39 | **凡勃伦效应** (Veblen Effect) | 价格越高,越有人买。 | **撇脂定价法** | 高端产品定价,收割高净值用户。 |
+| 40 | **帕金森定律** (Parkinson's Law) | 工作会自动膨胀占满时间。 | **番茄工作法** / **Timeboxing** | 强行限定截止时间 (Deadline)。 |
+
+---
+
+## 🛠️ 第五部分:产品、创新与工程
+**核心目标:做出用户真正需要的东西。**
+
+从“制造”思维转向“设计”思维。
+
+| 序号 | 思维模型 | 核心理念 | ⚔️ 落地方法论/工具 | 实战应用场景 |
+| :--- | :--- | :--- | :--- | :--- |
+| 41 | **MVP** (最小可行性产品) | 小步快跑,快速试错。 | **精益画布 (Lean Canvas)** | 一张纸写清商业模式,快速验证。 |
+| 42 | **PMF** (Product-Market Fit) | 产品与市场完美契合。 | **NPS (净推荐值) 调查** | 判断用户忠诚度与扩张时机。 |
+| 43 | **待办任务** (Jobs to be Done) | 用户买钻头是为了得到孔。 | **用户故事 (User Story)** | 敏捷开发中的需求定义。 |
+| 44 | **技术债务** (Technical Debt) | 速度牺牲质量,未来要加倍还。 | **SonarQube** / **偿债周** | 代码质量检测与定期修复。 |
+| 45 | **冗余/备份** (Redundancy) | 关键系统必须有备份。 | **RAID** / **灾备演练** | 系统高可用设计。 |
+| 46 | **标准化** (Standardization) | 减少变数,提高效率。 | **SOP (标准作业程序)** / **Checklist** | 确保小白也能操作,减少失误。 |
+| 47 | **规模效应** (Economies of Scale) | 产量越大,单位成本越低。 | **供应链管理 (SCM)** | 集中采购,降低边际成本。 |
+| 48 | **货柜崇拜** (Cargo Cult) | 模仿外表,不理解本质。 | *(去形式化)* | 避免盲目照搬大厂流程。 |
+| 49 | **断裂点** (Breakpoint) | 系统在压力下崩溃的临界点。 | **压力测试 (Stress Testing)** | 模拟高并发,测出系统极限。 |
+| 50 | **用户路径** (User Journey) | 从用户视角看全流程。 | **用户体验地图** | 优化转化率,发现体验断点。 |
+
+---
+
+## 👥 第六部分:组织管理与领导力
+**核心目标:带好队伍,分好钱。**
+
+管理是关于人类行为的杠杆。
+
+| 序号 | 思维模型 | 核心理念 | ⚔️ 落地方法论/工具 | 实战应用场景 |
+| :--- | :--- | :--- | :--- | :--- |
+| 51 | **彼得原理** (Peter Principle) | 人会被晋升到不胜任的位置。 | **九宫格人才盘点** | 区分业绩与潜力,避免错误提拔。 |
+| 52 | **邓巴数字** (Dunbar's Number) | 150人的管理极限。 | **双披萨原则 (Two Pizza Rule)** | 亚马逊法则:团队规模保持精简。 |
+| 53 | **激励机制** (Incentives) | 屁股决定脑袋。 | **OKR** / **ESOP (期权池)** | 目标对齐与利益绑定。 |
+| 54 | **破窗效应** (Broken Windows) | 坏事没人管,就会越来越多。 | **Code Review** / **6S** | 发现小问题立刻修复,维护文化。 |
+| 55 | **格鲁夫杠杆** (High Output) | 经理产出 = 团队产出。 | **1-on-1 会议** | 通过辅导下属撬动高产出。 |
+| 56 | **指挥官意图** | 告诉Why和What,别管How。 | **任务式指挥 (Mission Command)** | 充分授权,发挥一线主观能动性。 |
+| 57 | **皮格马利翁效应** | 期望越高,表现越好。 | **教练技术 (Coaching)** | 积极心理暗示,引导员工成长。 |
+| 58 | **责任分散** | 人越多,越没人负责。 | **DRI (直接负责人)** / **RACI** | 确保每个任务有且仅有一个负责人。 |
+| 59 | **群体极化** (Group Polarization) | 群体讨论容易导致极端。 | **德尔菲法 (Delphi Method)** | 匿名征求专家意见,避免随大流。 |
+| 60 | **学习曲线** (Learning Curve) | 熟能生巧,效率随经验提升。 | **入职培训清单 (Onboarding)** | 加速新人上手速度。 |
+
+---
+
+## 🧠 第七部分:心理学与人性误判
+**核心目标:洞察人性,营销与说服。**
+
+查理·芒格最推崇的领域,理解人类误判心理学。
+
+| 序号 | 思维模型 | 核心理念 | ⚔️ 落地方法论/工具 | 实战应用场景 |
+| :--- | :--- | :--- | :--- | :--- |
+| 61 | **社会认同** (Social Proof) | 大家都在买,所以我也买。 | **客户证言 / Logo墙** | 官网信用背书建设。 |
+| 62 | **稀缺效应** (Scarcity) | 越少越想要。 | **倒计时 / 限购令** | 电商逼单转化。 |
+| 63 | **互惠倾向** (Reciprocity) | 拿人手短,想回报。 | **内容营销 (白皮书/试用)** | 免费给价值,换取销售线索。 |
+| 64 | **承诺与一致** (Consistency) | 人倾向于遵守公开承诺。 | **登门槛效应 (Foot-in-the-door)** | 先求小承诺(点赞),再求大承诺。 |
+| 65 | **厌恶损失** (Loss Aversion) | 失去的痛苦大于得到的快乐。 | **无理由退款** / **试用期** | 消除客户顾虑,提升转化。 |
+| 66 | **锚定效应** (Anchoring) | 第一印象决定后续判断。 | **价格诱饵 / 价格锚点** | 设置高价套餐衬托主推款性价比。 |
+| 67 | **确认偏误** (Confirmation Bias) | 只看支持自己的证据。 | **红蓝军对抗 (Red Teaming)** | 找专人挑刺,攻击现有方案。 |
+| 68 | **幸存者偏差** | 死人不会说话。 | **流失分析 (Churn Analysis)** | 回访不再续费的客户,寻找真因。 |
+| 69 | **基本归因谬误** | 别人错是人品,我错是环境。 | **360度评估** | 多维度评价,避免单一视角偏见。 |
+| 70 | **这种鲁巴效应** (Lollapalooza) | 多种心理因素叠加产生爆炸效果。 | **营销漏斗 (Funnel)** | 在各环节叠加多种诱因促成转化。 |
+
+---
+
+## 🌊 第八部分:自然与物理隐喻
+**核心目标:从大自然借智慧。**
+
+| 序号 | 思维模型 | 核心理念 | ⚔️ 落地方法论/工具 | 实战应用场景 |
+| :--- | :--- | :--- | :--- | :--- |
+| 71 | **活化能** (Activation Energy) | 万事开头难,需最小能量启动。 | **用户引导 (Onboarding Flow)** | 极致简化注册/上手流程。 |
+| 72 | **催化剂** (Catalyst) | 加速反应但不消耗自己。 | **增长黑客 (Growth Hacking)** | 寻找低成本加速增长的手段。 |
+| 73 | **半衰期** (Half-life) | 事物衰减的速度。 | **内容审计 (Content Audit)** | 定期更新过时的文档或代码。 |
+| 74 | **惯性** (Inertia) | 改变现状需要巨大外力。 | **变革管理八步法** | 打破组织惯性,推行新政。 |
+| 75 | **相对论** (Relativity) | 参照系决定视角。 | **价格锚点** | 利用对比产生价值感。 |
+
+---
+
+## 📝 结语:如何使用这份清单?
+
+不要试图一次性背诵所有模型。建议将本文**收藏**或**打印**,作为您的“案头词典”。
+
+1.  **遇到管理难题时**(如团队内耗):查阅**第六部分**,尝试用 **RACI** 和 **SBI** 解决。
+2.  **制定年度战略时**:查阅**第二部分**,用 **VRIO** 和 **PESTEL** 进行扫描。
+3.  **产品推不动时**:查阅**第五部分**,看看是否满足了 **JTBD** 或卡在了 **跨越鸿沟** 阶段。
+
+思维模型不是为了让你看起来更聪明,而是为了让你在关键时刻,做出那个**胜率更高**的决定。

+ 205 - 0
source/_posts/AHA.md

@@ -0,0 +1,205 @@
+title: AHA
+author: Gamehu
+tags:
+  - AHA
+categories:
+  - 编程
+date: 2020-12-01 17:52:00
+---
+{% asset_img a.jpg [Collin Armstrong](https://unsplash.com/@brazofuerte)  %}
+
+### 背景
+
+干研发的有个高频词语:**抽象**,这个词语可应用于各种场景,我今天聊的是代码抽象,在此篇就比较low逼的理解成代码复用吧,不然感觉有点虚。
+
+为啥记录这个呢还是源于近段时间遇到的一些矛盾,重复代码该不该都抽出来,在这之前我会毫不犹豫的说应该,包括现在团队里也几乎是这样的声音,但是是不是就一定对呢?现在我觉得这个观点是不对的,因为我发现有些代码抽出来之后反倒变得越来越不可掌控。
+
+所以我在思考**克制抽象**是不是也应该提出来。为了验证这个思考,遂搜了搜,别说还真有那么些大佬早就提出了这个观点。
+
+#### AHA
+
+`AHA` (读作"[Aha](https://kentcdodds.com/blog/aha-programming)!" ):**Avoid Hasty Abstractions**(避免草率的抽象)
+
+读了几篇文章特别感动,尤其是Sandi Metz的 [The Wrong Abstraction](https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction),特别有共鸣。
+
+**核心观点就是**
+
+> 宁愿复制而不是错误的抽象
+
+具体的支撑**克制抽象**内容,这几篇文章说的很清楚了,我就不再来一遍了。
+
+##### 我就给个现实的例子
+
+```javascript
+/**
+ * 获取某个CI模型数据 v1.0
+ * @param {object} code 模型code
+ * @returns {object}  格式化之后的模型对象
+ */
+export const getCi = async (code) => {
+  const meta = await request.post('/api/v1/model/ci/getCi', { code });
+  // 绑定数据字典
+  meta.attributes = meta.attributes.map((item) => {
+    const attr = { ...item };
+    if (attr.changeValue === 'dict') {
+      if (!DICT.get(attr.code)) {
+        rlog.error(`找不到 ${attr.code} 对应的数据字典`);
+      } else {
+        attr.dict = DICT.get(attr.code).items;
+      }
+    }
+    return attr;
+  });
+  return meta;
+};
+
+/**
+ * 获取某个CI模型数据  v2.0
+ * @param {object} code 模型code
+ * @param {boolean} userVisibleFilter 是否按照模型的userVisible过滤,发现页面不过滤
+ * @returns {object}  格式化之后的模型对象
+ */
+export const getCi = async (code, userVisibleFilter = true) => {
+  const meta = await request.post('/api/v1/model/ci/getCi', { code });
+  // 获取过滤userVisible=true的属性(用户可见)
+  const { attributes } = meta;
+  const visibleAttributes = userVisibleFilter
+    ? attributes.filter((item) => item.userVisible)
+    : attributes;
+  // 属性绑定数据字典
+  meta.attributes = visibleAttributes.map((item) => {
+    const attr = { ...item };
+    if (attr.changeValue === 'dict') {
+      if (!DICT.get(attr.code)) {
+        console.error(`找不到 ${attr.code} 对应的数据字典`);
+      } else {
+        attr.dict = DICT.get(attr.code).items;
+      }
+    }
+    return attr;
+  });
+  return meta;
+};
+
+
+/**
+ *
+ * 获取某个CI模型数据 
+ * @param {object} code 模型code
+ * @param {boolean} userVisibleFilter 是否按照模型的userVisible过滤,发现页面不过滤
+ * @param {boolean} dict 是否需要绑定数据字典
+ * @returns {object} 格式化之后的模型对象
+ */
+export const getCi = async (code, userVisibleFilter = true, dict = true) => {
+  const { meta, visibleAttributes } = await formatMeta(code, userVisibleFilter);
+
+  if (!dict) {
+    meta.attributes = visibleAttributes;
+    return meta;
+  }
+
+  // 属性绑定数据字典
+  return bindDict(meta, visibleAttributes);
+};
+
+/**
+ *
+ * 获取某个CI模型数据  v3.0
+ * @param {object} code 模型code
+ * @param {boolean} userVisibleFilter 是否按照模型的userVisible过滤,发现页面不过滤
+ * @param {boolean} dict 是否需要绑定数据字典
+ * @returns {object}  格式化之后的模型对象
+ */
+export const getCi = async (code, userVisibleFilter = true, dict = true) => {
+  const meta = await formatVisibleAttributes(code, userVisibleFilter);
+  if (!dict) {
+    // 属性绑定数据字典
+    return bindDict(meta);
+  }
+  return meta;
+};
+
+/**
+ *
+ * 获取某个CI模型数据  v4.0
+ * @param {object} code 模型code
+ * @param {boolean} userVisibleFilter 是否按照模型的userVisible过滤,发现页面不过滤
+ * @param {boolean} dict 是否需要绑定数据字典
+ */
+export const getCi = async (code, userVisibleFilter = true, dict = true) => {
+  const meta = await formatVisibleAttributes(code, userVisibleFilter);
+  // 属性绑定数据字典
+  if (dict) {
+    try {
+      // 用户自建属性(数据字典)
+      const userDict = await getUserDicts(code);
+      return bindDict(meta, userDict);
+    } catch (error) {
+      rlog.error(error);
+      return meta;
+    }
+  }
+  return meta;
+};
+```
+
+```javascript
+/**
+ * 过滤可见属性
+ * @param {string} code
+ * @param {boolean} userVisibleFilter
+ * @returns {object}  只包含可见属性的模型对象
+ */
+async function formatVisibleAttributes(code, userVisibleFilter) {
+  const meta = await request.post('/api/v1/model/getCi', { code });
+  if (meta) {
+    let { attributes } = meta;
+    if (!attributes) {
+      return meta;
+    }
+    // 适配后端,使属性正序
+    attributes = attributes.reverse();
+    // 获取过滤userVisible=true的属性(用户可见)
+    if (userVisibleFilter) {
+      meta.attributes = attributes.filter(
+        (item) => item.userVisible === 'true'
+      );
+    }
+    return meta;
+  }
+  return meta;
+}
+```
+
+
+
+###### 如上所示
+
+> 总共经历了至少4次的改动,逻辑变得越来越复杂,因为需要适配多种场景,本来我一开始抽出来,理由很简单,因为该api是一个获取底层数据的api,大多数前端的功能都需要调用该api,且都是需要有数据字典的,因为要正确的展示数据,所以我抽了一个方法。
+>
+> 这个时候还是很美好的,不过后续就像 [The Wrong Abstraction](https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction)里写的一样,各个使用方或找我或自己对该方法进行了扩展,这方法那是叫惨不忍睹啊,就这还是我重构之后的样子,没重构之前更丑。
+>
+> 那有人就问了,为什么就扩展了呢?
+>
+> 1. 个人风格问题,该方法之前满足我得需求现在不满足了,所以我要改它,这样最简单,我可不管其它模块需不需要这个逻辑。
+> 2. 我也知道可能在上面加不太合适,因为加的扩展逻辑不是所有模块都需要的,但是也不是我一个人需要的,比如A、B、C、D...,A、B都需要,那为了不重复写代码,在原有方法上扩展我觉得也还行。
+> 3. ...
+>
+> 后来当我发现的时候,我就在群里发出了一个共识。
+>
+> 1. 这类公共的api原则上不加*个性化的扩展*但是可加通用性(不影响整体数据结构且没有业务逻辑,比如:对原始数据进行数据筛选(eg:可见、不可见))的扩展,且加的时候需要与该api的最初作者对齐。
+> 2. 如果要扩展个性化,请自行copy一份代码再修改。
+>
+> 我的理由是如果再这么搞那我就不维护了爱咋咋滴....................当然前面是意淫的咱们是一个team,和为贵。
+>
+> **真正的理由是维护成本会越来越高且与当初抽象的意义渐行渐远。**
+
+可能我给的例子不够有足够力量的说服力,但是我还是觉得,抽象不一定就一定时好的必须的,有些时候我们得反过来想想,任何事情都有两面性。虽然咱没有能力提出牛逼得理论和观点,但是我们可以基于大佬们提出得理论和观点,做些反思、验证...。
+
+有句话不是说吗:**站在巨人的肩膀上。这句话我理解不是说巨人的肩膀才稳,而是说能看得更远。**
+
+##### You Know 
+
+Duplication is far cheaper than the wrong abstraction
+
+`本文引用的内容,如有侵权请联系我删除,给您带来的不便我很抱歉。`

BIN
source/_posts/AHA/a.jpg


+ 66 - 0
source/_posts/AI应用-知识库.md

@@ -0,0 +1,66 @@
+title: AI应用-知识库
+author: Gamehu
+tags:
+  - AI
+categories:
+  - 学习
+date: 2024-03-12 22:31:00
+---
+<div class="tag-container">
+  <span class="ai-tag">AI</span>
+  <span class="sub-tag">第一篇</span>
+</div>
+
+## 背景
+这篇文章拖了很久了。因为我之前带LMT团队,团队的主要工作内容就是处理客户现场问题,因为我要求过程留痕并且达到知识沉淀的效果,所以处理过程中产生了大量的文档,也就是很多经验都落到了文档上,比如linux系统(硬盘、系统版本、dns等)、docker、k8s、现场网络问题(防火墙、网闸等安全设备),也就是运维经常面临的问题,也有产品配置、bug等文档。
+
+文档越来越多,但是却越来越难利用起来,我就想着把这些经验积累起来弄一个知识库,就像gpt一样,只要我输入有关问题他就能根据这些内容生成回答的内容,当然里面不仅仅是经验问答还需要有linux系统(硬盘、系统版本、dns等)、docker、k8s、现场网络问题(防火墙、网闸等安全设备)这些原始(原理)知识,还得有我们的产品知识。
+
+这个知识库一是为了方便使用且能让我练手,二是当时公司推行创新活动,AI相关的案例也能为事业部加分。
+
+## 开始
+
+知识库的定位:小而美,因为是个人发起的前期申请到的服务器资源有限,而且功能非常单一明确,只需要满足知识库就行,不需要全能。
+
+### 选型
+
+通过一通查找对比,综合考虑,选择了Anything LLM或者Dify.AI+Ollama+Llama2小模型。
+
+#### Anything LLM 
+![alt text](<llm.png>)
+
+#### 考虑的其中一点
+**是用Anything LLM这种开箱即用的还是用LangChain这种需要自己上手写代码的**
+Anything LLM和Dify.AI在其架构中广泛使用了LangChain组件,尤其是:
+
+- 文档加载器(Document Loaders)
+- 文本分割器(Text Splitters)
+- 向量存储(Vector Stores)
+- 检索器(Retrievers)
+
+1. 直接使用Anything LLM这种系统的好处
+   1. 意味着即使不直接编写LangChain代码,您也在间接使用LangChain的强大功能。这有几个好处:
+      模块化设计 - 可以灵活替换组件(如切换向量数据库)
+      经过验证的架构 - 使用业界已验证的RAG实现方式
+      未来升级路径 - 如果您将来想更深入定制,可以直接使用LangChain API
+2. 坏处
+   1. 没有深入的了解和实践经验
+
+我当时其实想用LangChain的,环境都搭好了,但是因为没有系统的学习过,进度很慢,没法赶上评审节点,所以最终选择了使用Anything LLM这种简单的方式。
+
+### 验证
+
+Anything LLM+Ollama试了几种模型和Embedder,最终勉强得出一个组合Llama2:7B-chinese+bge-m3
+还需要调整文档本身的内容,以及一些参数再多次尝试。
+
+待续...
+
+
+
+
+# 参考
+https://docs.useanything.com/setup/llm-configuration/overview
+https://github.com/Mintplex-Labs/anything-llm/blob/master/docker/HOW_TO_USE_DOCKER.md
+https://adasci.org/anythingllm-for-local-execution-and-inferencing-of-llms-a-deep-dive/
+https://itnext.io/deploy-flexible-and-custom-setups-with-anything-llm-on-kubernetes-a2b5687f2bcc
+https://www.youtube.com/watch?v=4UFrVvy7VlA

BIN
source/_posts/AI应用-知识库/llm.png


+ 91 - 0
source/_posts/Agent-Skills-superpowers.md

@@ -0,0 +1,91 @@
+title: 别再手写 Prompt 了!Skills.sh:AI Agent 的“神技”一键注入指南
+tags:
+  - AI Agent
+  - Skills
+categories:
+  - AI
+date: 2026-01-27 11:35:00
+---
+<div class="tag-container">
+  <span class="ai-tag">Skills</span>
+</div>
+在软件研发进入 Agent 时代的今天,你是否还在一遍遍给 Cursor 或 Claude Code 发送长长的“咒语”?
+
+现在,有一个更优雅的解决方案:**[Skills.sh](https://skills.sh/)**。它正在把 AI 的能力标准化,让你像安装 npm 包一样,一键给你的 AI 助手增加“神技”。
+
+## 🚀 什么是 Skills.sh?
+
+**Skills.sh** 是一个开放的 AI 智能体技能生态系统。它允许开发者将特定的**领域知识、操作指令和最佳实践**封装成“Skills(技能)”。
+
+通过一行简单的命令,你就可以把这些技能安装到你的 AI 开发环境(如 Cursor, Trae, Windsurf, Claude Code 等)中。
+{% asset_img 1.jpg %}
+
+### 核心操作命令
+```bash
+# 安装一个特定的技能
+npx skills add <owner/repo>
+
+```
+
+---
+
+## 💎 GitHub 明星技能库大盘点
+
+Skills.sh 本身是一个聚合器,真正的力量来自于 GitHub 上那些被“开源精神”填满的仓库。以下是目前最值得关注的三个顶级仓库:
+
+### 1. 📂 `everything` —— 全能的工具箱
+
+如果你不知道装什么,先看 `everything`。它致力于覆盖开发者日常的方方面面。
+
+* **核心价值**:从文件处理、代码重构到 UI 组件设计,它试图通过一套标准让 AI 处理“任何事情”。
+* **推荐技能**:`everything/refactor`, `everything/ui-polish`
+
+### 2. 😎 `awesome-agent-skills` —— 精选推荐集
+
+类似于我们熟悉的 GitHub Awesome 列表,这里汇集了社区中经过验证的高质量技能。
+
+* **核心价值**:它是技能界的“米其林指南”。如果你追求稳定和官方认可的实践,这里是首选。
+* **推荐内容**:涵盖了针对 React、Rust、PostgreSQL 等各个领域的专家级配置。
+
+### 3. ⚡ `superpowers` —— 赋予 AI “思考逻辑”
+
+这是我个人最推崇的库。它不只是教 AI 写代码,而是教 AI **“如何思考”**。
+
+* **核心价值**:注入了深度的工程化思维。
+* **明星技能**:
+* `superpowers/systematic-debugging`: 让 AI 按照逻辑排除法寻找 Bug,而不是乱猜。
+* `superpowers/planning`: 强制 AI 在动工前先写技术方案,这对于复杂重构至关重要。
+
+
+
+---
+
+## 🛠️ 如何集成到你的工作流?
+
+作为一名研发负责人,我推荐以下集成路径:
+
+### A. 针对个人开发者(Cursor 用户)
+
+在你项目根目录下执行:
+
+```bash
+npx skills add vercel-labs/agent-skills
+
+```
+
+这会在你的项目里生成或更新 `.cursorrules` 文件,让 Cursor 自动感知并遵循 Vercel 级别的开发标准。
+
+### B. 针对团队协作
+
+你可以创建自己公司的专属 `skills` 库。
+
+1. 将常用的 **API 异常定义**、**多租户处理逻辑**封装成 Skill。
+2. 团队成员统一安装。
+3. **效果**:AI 写的每一行代码,都像是你团队的老员工写出来的。
+
+
+## 结语
+
+**Skills.sh** 的出现标志着 AI 辅助开发进入了“模块化”时代。我们不再需要去记复杂的 Prompt 技巧,而是通过**社区共建**,直接复用全球最顶尖开发者的思维模型。
+
+如果你还没试过,建议现在就去 [skills.sh](https://skills.sh/) 寻找适合你的那款“超能力”。

BIN
source/_posts/Agent-Skills-superpowers/1.jpg


+ 139 - 0
source/_posts/CMDB.md

@@ -0,0 +1,139 @@
+title: CMDB
+author: Gamehu
+tags:
+
+  - CMDB
+categories:
+  - DevOps
+date: 2020-08-27 14:18:00
+---
+### 背景
+
+之前有提过现阶段要把之前的产品推翻重做,做带中台调性的新监控。其中一块核心的内容就是CMDB,虽然CMDB的设计主要是架构师以及后端同学的活,但是架不住我爱掺合啊,这块的前端是我来弄,所以也有正当理由摸鱼撒。所以简单也做个记录,稍微深入的了解下CMDB这玩意,也不能细说一个是我没那么精通另一个我不得保护我们的产品知识产权吗不然老板不把我弄死啊...跑题了。
+
+### 开始
+
+CMDB刚开始接触的时候我把它笼统的理解为资产管理,当然这种理解肯定是不对的,太局限。
+
+因为我们的产品大多数情况下都是部署在客户的内网,CMDB在我们产品中的定位:
+
+- 运维对象管理系统。
+- 支撑监控能力的基础设施。
+- 以应用为核心对象串联其它资源。
+
+**识别运维对象,主要分为两个部分:**
+
+基础设施层面:网络设备、服务器、存储设备等;
+
+应用层面:应用元信息、告警配置信息等
+
+当我们识别出运维对象和对象间的关系,并形成了统一的标准之后,接下来要做的事情就是将这些标准固化,固化到信息管理平台中,也就形成了我们说的CMDB(配置管理)。
+
+#### 运维对象识别
+
+思路跟下图很像,从消费场景入手,识别对象以及对象具有的元素应该有哪些。
+
+{% asset_img  1.jpg 公众号-高效运维 %}
+
+{% asset_img  2.png 公众号-高效运维 %}
+
+最终细化一下会识别出几种类型,一个是**基础资源对象**,一个是**应用对象**,一个是**逻辑对象**(组织和人),把这几种类型对象按照相应的规则的建立关系,从而管理属性、关系、状态、场景。
+
+#### 发现
+
+前一小结确定了运维对象识别的核心思想,其中一个大的作用就是指导**资源发现**,我们第一版的发现的方式包含两种:
+
+- 网络拓扑发现(自动):通过SNMP扫描网络,发现其中的网络设备,并判定其间的网络连接关系。
+
+- 指定类型发现(人工或者流程):用户指定资产类型,发现时不需要依据判定规则。
+
+  下图是我傍的一个后端大佬画的,我悄悄盗过来,镇场面。
+
+```mermaid
+classDiagram
+
+	class 发现规则 {
+		+ 判定规则
+		+ 收集规则
+	}
+
+	
+	任务 "1" -- "N" 任务执行
+	发现代理 -- 发现结果
+	任务执行 -- 发现代理
+	任务执行 -- 资产数据
+	资产数据 -- CMDB
+
+	发现规则 -- 发现代理
+	全局例外 -- 发现代理
+	SNMP特殊判定 -- 发现规则
+	任务 "1" -- "N" 连接信息
+```
+
+
+
+#### 建立关系
+
+首先明确一点,以`应用为中心`,从应用的视角去看,从应用的角度构建资源管理的关系(拓扑关系)。
+
+看了几篇相关的文章基本上,关系类型可简化为下面几种:
+
+- 主从关系。这种关系是一种强父子关系,主不存在了,则从就不存在了。比如主机和网卡、硬盘。
+- 依赖关系。是一种对象属性级之间的关联关系,比如说服务器放在机柜上,机柜摆在某个机房内,这是对象级别的关系。通过对象的属性关联来表达。
+- 连接关系。主机和存储、主机和网络设备的关系,是连接关系。这种关系是动态生成的,是一种实例级的关系。
+
+依赖关系和连接关系有什么不同?
+
+- 依赖是一对多的关系,并且这个关系是靠人维护的,比如说机柜上放了很多服务器。
+- 连接是多对多关系,并且这个关系是因为某种“连接”产生的,比如说服务器连接了交换机。通常是通过自动发现来实现。
+
+{%asset_img 3.png  公众号-互联网运维杂谈 %}
+
+我们产品第一版关系设计跟上诉差不太多,只是叫法有一些区别。
+
+> 比如主从关系:属于、包含。
+>
+> 依赖关系:运行在
+>
+> 连接关系:连接
+
+
+
+由于各种原因,大概就整理这么多。
+
+### 小结
+
+大体围绕CMDB的设计思路如下图。
+
+{%asset_img 4.png  me %}
+
+**设计的时候考虑的要点:**
+
+1. 领导要参与,团队理解要一致。通过场景带入的方式。
+2. `领域`分析是核心,除非有必要,不然不考虑技术实现。
+   1. 为啥DDD,建立研发、产品等各方的通用语言。
+   2. 为啥DDD,DDD是一套完整而系统的设计方法,基于这套方法使面对高复杂度的业务,设计思路能更加清晰,设计过程也能更加规范。
+3. 从应用视角切入,应用是核心。
+4. CMDB最好分为两个维度的内容进行共创:配置管理、资源管理(资源管理 ≠ 资产管理)。
+5. 整理的资源都是服务于各种消费场景的,原则上不应该存在游离态的资源。
+6. CMDB的模型定义一定是有层次的,比如分为核心模型和扩展模型。
+   1. 核心模型记录业务、应用和主机,有了核心模型系统基本就能跑起来了。
+   2. 扩展模型是依赖核心模型扩展出来的,比如基于主机找到关联的机柜等信息,这块信息是有核心模型驱动逐步完善的。
+
+`本文引用的图片,如有侵权请联系我删除。`
+
+
+
+#### 感谢
+
+{% blockquote 优维科技 高效运维 https://mp.weixin.qq.com/s?__biz=MzA4Nzg5Nzc5OA==&mid=2651674578&idx=2&sn=939e98e465b7f1a7bb0b241027a46515&chksm=8bcb947bbcbc1d6d5a4928f209f81aede528233f9b0657dd931735d5730c57674885099cd2f7&mpshare=1&scene=1&srcid=0819MkW8c80sVuYCmwUpP13Z&sharer_sharetime=1597831810952&sharer_shareid=77df2eafd0a472623696abf038541666&version=3.0.27.2701&platform=win&rd2werd=1#wechat_redirect   构建应用CMDB需掌握的三个要素:资源、动作和状态 %}
+{% endblockquote %}
+
+{% blockquote 老王 互联网运维杂谈 https://mp.weixin.qq.com/s/iSEw5eVrTrHXjrHP0b1K0g?st=E6D56F7C7B073C5CA0BE786C5363D3A81166FAEBE74EB9D48310237737FC81BD8E64D2FFDEEFBC38EDA177DA423B6883F2B6561AE7376BE1C85EFBCD908AA2B3DE7BB684878EFBE2E586376BB913EE53E2D08AA0984CD4DFBD27CCDCF0F8AAB16CBDC85E4AB545F1397E0650A753DB1066E4FC0020796E606A4D511395EC7BC2&vid=1688851803314412&cst=3B9A8FB5F8073A54B16F68BFD18A87478E098A6169FFDD65418DADA3EC51851EC020FA4E767BF96883B70D4BC62638E2&deviceid=c9cb6c9b-5ea8-4bb7-87a6-280f14284b4f&version=3.0.27.2701&platform=win  如何理解CMDB的套路 %}
+{% endblockquote %}
+
+
+
+{% blockquote 资源模型 https://zstack-cn.readthedocs.io/zh/latest/userManual/resource.html zstack%}
+{% endblockquote %}
+

BIN
source/_posts/CMDB/1.jpg


BIN
source/_posts/CMDB/2.png


BIN
source/_posts/CMDB/3.png


BIN
source/_posts/CMDB/4.png


+ 41 - 0
source/_posts/CSS Triggers.md

@@ -0,0 +1,41 @@
+title: CSS Triggers
+author: Gamehu
+tags:
+
+  - css
+categories:
+  - 前端
+date: 2018-09-11 14:46:00
+
+---
+
+在学习浏览器那块,有一块时关于渲染的。
+
+{% asset_img render.png %}
+
+在此过程中发现了一个[网站 CSS Triggers](https://csstriggers.com/),说明哪些css可以触发浏览器的重新渲染(`layout`、`Paint`、`Composite`),所以这个网站是用来告诉开发者不同内核浏览器对css属性修改的重绘/回流情况,开发者知道了这些细节可以提高页面性能。
+
+小而美的网站,感谢这两位大佬 [Paul](https://twitter.com/aerotwist) and [Surma](https://twitter.com/DasSurma)。
+
+我在此简单做个记录,方便后续的使用。
+
+
+
+
+
+### 说明
+
+- 紫色代表如果layout,中文一般翻译成布局。
+- 浅绿色代表Paint,一般翻译成重绘。
+- 深墨绿色代表Composite,翻译成混合或者合成,重绘和回流任意发生一个就会引起Composite。
+
+
+
+#### 触发时间:
+
+- Change from default:设置属性(从默认值修改,相当于一开始没设置css)
+- Subsequernt updates:修改属性(对现有的属性值进行修改)。
+
+如图所示,点击每个属性会有详细的说明。
+
+{% asset_img css.png %}

BIN
source/_posts/CSS Triggers/css.png


BIN
source/_posts/CSS Triggers/render.png


+ 134 - 0
source/_posts/Chrome Tools-Sources.md

@@ -0,0 +1,134 @@
+title: Chrome Tools-Sources
+tags:
+  - 实践
+categories:
+  - 工作
+date: 2019-09-20 14:29:00
+---
+嗯,跟前端暧昧的时间还是挺长了,是时候展现真正的技术了。
+
+{% asset_img 1.jpg %}
+
+常在写代码哪有不bug的道理,那对于前端朋友来讲chrome的工具栏基本上能满足大多数场景下的bug排查,对于奉行**假如你暂时不够牛逼,那就善用工具**的我来说,我心荡漾啊。必须记录一下,当然chrome提供的工具太多了,今天暂且主要聊聊Sources,也是我使用频率Top 2,结合一些网上的一些说明加自身的实践来说一说。
+
+{% asset_img Inked0_LI.jpg 就是这玩意%}
+
+不用再于数字不好看这些细节,我们走的是放荡不羁的路线,咱们挨个说啊。
+
+<style> table th:first-of-type { width: 80px; } </style>  
+
+|  数字   | 表头  |
+|  ----  | ----  |
+| 1  | 点击该箭头,移动鼠标到页面上定位到页面元素,跳转到Elements 工具栏。  |
+| 2  | 用于模拟移动设备上的效果。   |
+| 3  |  必用的模块,已加载的全部资源,以域名划分文件夹,调试时从这儿下手找源码,当然我通常直接快捷键Ctrl+P定位文件。 
+| 4、5 |   Filesystem & Overrides 可以加载本地文件夹,把Chrome当成IDE用。 
+| 6  |   Content scripts 扩展工具的脚本,比如百度翻译插件等 
+| 7  |   Snippets 代码片段,不会因为刷新丢失,使用:添加=>保存(ctrl+s)=>运行(Run)=>不用则移除(Remove) 
+| 8  |   源码面板,在此处进行打断点、修改端点等操作 
+| 9  |   调试的快捷键面板 
+| 10 |   变量监察:添加个变量后会一直监察这个变量的值,当前作用域无值时显示< not availble > 
+| 11 |   Call Stack 函数调用栈,会列出断点的调用堆栈列表。 
+| 12 |   Scope 断点所在作用域列表,级别划分如下: <ul> <li>Local 当前作用域 展示作用域下的变量</li><li>Closure (x) 闭包作用域,x是函数名称</li><li>Script 标签作用域</li><li>Global 全局作用域Window</li></ul> 
+| 13 |   Breakpoints 源码的断点列表。 
+| 14 |   XHR/fetch Breakpoints 请求断点:ajax和fetch请求都可以在这里打断点并在Call Stack显示调用栈,很方便追踪。 
+| 15 |   DOM Breakpoints 这里列出html的断点。 
+| 16 |   Global Listeners 全局监听器:指的是绑定在 window 对象上的事件。 
+| 17 |   Event Listeners Breakpoints 所有事件的断点:勾选指定类型,比如Mouse/click,则所有的click事件都会被断住。   
+
+markdown搞出这个表格太费劲,anyway看着舒服就好,下面聊聊对应上面表格中的一些具体的使用场景。    
+
+- Filesystem Chrome式的IDE,可以编辑各种文件并且在当前页就可以实时刷新看到效果,如果写单个模块时蛮有用的,比较快。修改后ctrl+s保存,修改的是本地文件,刷新可看到效果。   
+
+{% asset_img Filesystem.gif 演示一哈 %}   
+
+- Overrides 覆盖网络请求的资源,即html、js、css、图片等资源,注意一定是同域名同路径同名的文件才能产生覆盖效果。勾选,Enable Local Overrides,修改文件后ctrl+s保存,修改的是Save as Overrides到本地的文件,刷新可看到效果。  
+ {% asset_img network-overrides.gif 这个就不亲自演示了,网上找一个 %}  
+
+- <span style=color:#17640E;background-color:#DDA71D;>**Snippets**</span>,也是我使用比较多的功能,以前不知道的时候都是找网上现场的js编辑器,但是受网络和维护的影响,有些时候不好用,而且很多还要区分ES5、ES6,自从有了Snippets,随便写各种代码片段超级好用。     但是要注意变量的作用域问题,所以最好用IIFE方式写代码,避免出现错误。  {% asset_img snippets.gif 演示一波 %}  
+
+### 源码面板 ### 
+- 这也是调试的时候使用频率超级高的区域,ctrl+p定位到文件,行号处右键出现对断点操作的一些选项,分新增和编辑两类。  
+
+{% asset_img breakpoints.gif 演示一波 %} 
+
+ - Add conditional breakpoint/edit breakpoint ,添加/修改带条件的断点,比如写a==="a",则表示当a等于"a"时才触发断点,如下图。当条件表达式为真时,触发断点(条件性行断点的颜色为橙色)
+
+{% asset_img debug03.gif %}
+
+ - Blackbox Script,黑盒脚本,很多时候是要引用第三方库或框架的,当我们调试时,调试的对象应该是我们自己写的代码,但很多时候,我们经常在焦灼地进行下一步下一步时,突然代码跳到了第三方库或框架的源码上去,多数情况下我们不会关注这些地方的内容,但是它就要跳过去,这种是比较蛋疼的。黑盒脚本就是用来解决这个问题的,它能够把一个脚本文件标记为 "Blackbox Script",那么我们就永远不可能进入这个文件内部,这个文件对我们来讲就是一个黑盒子。为什么要强调“永远”呢?因为不仅普通的断点不能访问这个被标记了的脚本,其他的,比如说 DOM 断点、事件断点等等都无法访问那个脚本文件内部。
+
+- 调试面板:Pause on exceptions,在发生异常的地方停顿
+
+{% asset_img debug04.gif %}
+
+
+### Watch面板 ###
+- 用于监视变量的值。
+{% asset_img watch.png %}
+
+点击<span style=color:red;>**1**</span>处,将打开一个内联输入框,您可以在输入框中输入要监视的变量名称。输入完毕,按Enter键,即可将其添加到列表中。监视器将显示添加时变量的当前值。如果变量未设置或找不到,值将显示为<Not Available>。
+
+点击<span style=color:red;>**2**</span>手动刷新变量。注:监视列表不是变量的实时视图,除非逐步执行。当使用断点逐步执行时,监视列表中的值将自动更新
+
+点击<span style=color:red;>**3**</span>,删除变量。
+
+### Call stack ###
+
+代码暂停时,可以在Call Stack窗口查看当前的调用栈。展示了代码到暂停处的完整执行路径,这让我们能够深入代码去找出导致错误的原因。最后调用函数在最顶上,所以最好别用匿名函数,不利于调用栈查看。
+
+### Scope ###
+
+作用域:显示断点所在的作用域,级别划分如下:
+
+Local 当前作用域 展开作用域下的变量
+Closure (x) 闭包作用域,x是函数名称
+Script 标签作用域
+Global 全局作用域Window
+
+### DOM Breakpoints ### 
+
+当改变一个节点或者其子元素时,可以设置一个DOM断点:
+
+1. 点击Elements面板 
+1. 找到想要设置断点的元素 
+1. 在此元素上右键
+1. Break on --> Subtree modifications / Attribute modifications / Node removal
+	
+	Subtree modifications(子树修改):当前选中的元素,删除、增加其子代或者改变其子代的内容。修改子元素的属性或者当前选中元素有任何改变都不会触发此类型断点
+	Attributes modifications(属性修改):当前选中的元素,增加、删除其属性,或者修改某个属性值
+	Node Removal(节点移除):移除当前选中的元素
+
+### XHR/Fetch Breakpoints ###
+
+当XHR的请求URL包含某一特定的字符串时,可以暂停调试代码。DevTools会在XHR调用send()那行代码的地方暂停。
+
+1. 点击Sources面板 
+1. 展开XHR Breakpoints小窗口
+1. 点击“增加断点(Add breakpoint)”
+1. 输入一个字符串,只要在某个XHR的请求URL中包含此字符串, 会进入断点(暂停),如下图。 
+
+{% asset_img xhr.gif %}
+
+### Event Listeners Breakpoints ###
+
+这个断点类型也算是比较常用的一个了,特别是当我们调试别人的代码时,触发某个事件,想找到对应的代码。事件类型可以是很具体的,比如click事件,也可以是某一类别的事件,比如“鼠标事件”。
+1. 点击Sources面板
+1. 展开Event Listener Breakpoints小窗口
+1. 勾选某一类别的事件或者是某一具体的事件
+
+PS:
+
+{% asset_img point_types.png 南风一溅-https://juejin.im/user/5754e1575bbb500064496593 %}
+
+感谢:
+
+{% blockquote 无名小贝勒 https://segmentfault.com/a/1190000008396389  Chrome DevTools — JS调试 %}
+{% endblockquote %}
+{% blockquote lsc183 https://www.cnblogs.com/lsc183/p/9915285.html  Chrome DevTools 的 Sources 调试
+  %}
+{% endblockquote %}
+{% blockquote QAQ-YS https://zhuanlan.zhihu.com/p/80768870  使用 chrome-devtools Sources 面板 %}
+{% endblockquote %}
+
+`本文引用的内容,如有侵权请联系我删除,给您带来的不便我很抱歉。`

BIN
source/_posts/Chrome Tools-Sources/0.png


BIN
source/_posts/Chrome Tools-Sources/1.jpg


BIN
source/_posts/Chrome Tools-Sources/10.png


BIN
source/_posts/Chrome Tools-Sources/Filesystem.gif


BIN
source/_posts/Chrome Tools-Sources/Inked0_LI.jpg


BIN
source/_posts/Chrome Tools-Sources/breakpoints.gif


BIN
source/_posts/Chrome Tools-Sources/debug.png


BIN
source/_posts/Chrome Tools-Sources/debug03.gif


BIN
source/_posts/Chrome Tools-Sources/debug04.gif


BIN
source/_posts/Chrome Tools-Sources/network-overrides.gif


BIN
source/_posts/Chrome Tools-Sources/point_types.png


BIN
source/_posts/Chrome Tools-Sources/snippets.gif


BIN
source/_posts/Chrome Tools-Sources/watch.png


BIN
source/_posts/Chrome Tools-Sources/xhr.gif


+ 20 - 0
source/_posts/Clean Architecture.md

@@ -0,0 +1,20 @@
+title: The Clean Architecture
+author: Gamehu
+tags:
+  - 前端
+categories:
+  - 工作
+date: 2021-06-04 14:34:00
+---
+
+ 
+
+https://www.phodal.com/blog/clean-frontend-architecture-in-action/
+
+https://github.com/WebHu/clean-frontend/tree/master/src/app
+
+https://phodal.github.io/clean-frontend/#clean-frontend-architecture%EF%BC%9A%E6%95%B4%E6%B4%81%E5%89%8D%E7%AB%AF%E6%9E%B6%E6%9E%84
+
+https://medium.com/sharenowtech/front-end-architecture-making-rebuild-from-scratch-not-so-painful-7b2232dc1666#id_token=eyJhbGciOiJSUzI1NiIsImtpZCI6IjZhMWQyNmQ5OTJiZTdhNGI2ODliZGNlMTkxMWY0ZTlhZGM3NWQ5ZjEiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJuYmYiOjE2MjMxMzU0NTUsImF1ZCI6IjIxNjI5NjAzNTgzNC1rMWs2cWUwNjBzMnRwMmEyamFtNGxqZGNtczAwc3R0Zy5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsInN1YiI6IjExNzc4NDE0MDYzNzYyMDYwMjU0NSIsImVtYWlsIjoiZ2FtZWh1NTIwQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJhenAiOiIyMTYyOTYwMzU4MzQtazFrNnFlMDYwczJ0cDJhMmphbTRsamRjbXMwMHN0dGcuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJuYW1lIjoiR2FtZSBIdSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS0vQU9oMTRHZ2IyRm1vcGVMX3BISDVGcGg1NWxSN0hNWlJKdDVZZlU1bndNRT1zOTYtYyIsImdpdmVuX25hbWUiOiJHYW1lIiwiZmFtaWx5X25hbWUiOiJIdSIsImlhdCI6MTYyMzEzNTc1NSwiZXhwIjoxNjIzMTM5MzU1LCJqdGkiOiIzZDlmOGE1ZDQ4YjVhNzU4NjE4OTU0MGUxNjhhNWE2MDY5MTgyNTFjIn0.PhtrQiCnK5BF7FUt8pXbs9iEnGe1myxq7jX_ddIqheaCtej9-Hg0vXb1fT179frQHFdMvSZVdUZclegeZBd-YuMIBYNnuDLu0aATYMNljPUjKGgbTllM0Fqe2RYZqJuFP7ij4_0yyeFsGodOIac6eNcrOliR7kVj61SV_dpHwy1oF_gT3Qr9Ci8GHGuFipm-YV0Sc0yqlPuNr8zIQAnPK-c7I2bN1Oc1O8ikaLLCpZasidUAmP22yvHehwcR6WvdjA8ZEKJAaUCBzoYQlFrxTD9onHx8MhDvf503h3J8ti3ss4IXTT9kz97K3-im5SVCIHrcjC61TYMFfUPaHZN95A
+
+https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

+ 53 - 0
source/_posts/Code Review.md

@@ -0,0 +1,53 @@
+title: Code Review
+author: Gamehu
+tags:
+  - 实践
+categories:
+  - 工作
+date: 2018-08-01 09:47:00
+---
+
+以前我对code review是抗拒的,原因在于两方面:
+
+1. 总感觉有点脱光了让人看的感觉,没脸。
+2. 觉得是浪费时间,研发周期时间都不够还做什么code review。
+
+不过后来发现之前的自己是多么愚蠢
+
+{% asset_img code_review_hierarchy.png   %}
+
+
+
+## Why ##
+
+- 倒逼团队成员写出更有质量的代码
+> (基于编码规范等),让代码可以更好的组织起来,有更易读,有更高的维护性,同时可以达到知识共享,找到bug只是其中的副产品
+
+- 确认自己的设计和实现是一个清楚和简单、正确的
+> 并且通过review找到问题代码,减少错误和暗坑
+
+- 让更多的人了解你所写的模块,并能促进相互学习对方的长处和优点。
+- 提前暴露影响性能和安全的问题
+
+
+{% asset_img cr001.png   %}
+
+
+## When ##
+
+- 自动化测试之后,提测之前
+- 前后端联调之后(如果自动化测试还没实现)
+
+## What ##
+评判标准
+
+- 编码规范(比如后端《阿里编程规范》,前端ESLint)
+- 需求覆盖度是否100%
+- 测试用例覆盖度至少满足80/20原则
+
+
+## How ##
+
+- 提升团队意识,让大家知道code review的好处和重要性,切忌别把时间安排与code review拿在一起说,它们是两回事,时间够不够条件够不够跟code review好不好无关。
+- code review落实到产线的专项目标,指定责任人。 
+- 组件core view 团队,定义code view的关注点,持续改进。

BIN
source/_posts/Code Review/001.png


BIN
source/_posts/Code Review/002.png


BIN
source/_posts/Code Review/003.png


BIN
source/_posts/Code Review/004.png


BIN
source/_posts/Code Review/005.png


BIN
source/_posts/Code Review/code_review_hierarchy.png


BIN
source/_posts/Code Review/cr001.png


+ 19 - 0
source/_posts/DDD-1.md

@@ -0,0 +1,19 @@
+title: DDD(1)
+author: Gamehu
+tags:
+  - DDD
+categories:
+  -  架构师
+date: 2020-09-09 15:56:00
+---
+### 背景
+
+前面提到过我们要从头做一个产品,暂定代号”新监控“,现阶段是进行概设、预研等阶段,因为涉及到很多模块做概设,业务专家、产品经理、研发、测试等在参与,为了能更有效的产出,所以架构组拎出来了DDD,借用DDD这一套东西期望能让大家跑的更顺一些,当然DDD也仅仅是当成工具来使用,不生搬硬套。
+
+### DDD
+
+我知道DDD是,前几年突然就有很多文章提了这个概念挺火的(后面好像有段时间又有很多吐槽DDD的文章),为了了解是个啥玩意,我还还专门买了本书`领域驱动设计`,说实话没看完,对当年的我来说有点抽象了,因为经历的少了,找不到对应的场景来理解DDD,所以暂时就搁置了,刚好借这个机会,基于实践来学习这玩意,看到底咋样。
+
+先把架构师给的一些资料做个记录
+
+{%asset_img 1.png %}

BIN
source/_posts/DDD-1/1.png


+ 28 - 0
source/_posts/DevOps实践.md

@@ -0,0 +1,28 @@
+title: DevOps实践
+author: Gamehu
+tags:
+
+  - DevOps
+categories:
+  - 工作
+date: 2020-03-06 15:45:00
+
+---
+
+搬运[DevOps实施手册](https://devops.phodal.com/manual#%E6%80%BB%E8%A7%88)
+
+
+
+1. [建立愿景与方向](https://devops.phodal.com/manual#建立愿景与方向)
+2. [度量:组织、系统现状](https://devops.phodal.com/manual#度量)
+3. [准入条件](https://devops.phodal.com/manual#准入条件)。查看是否满足实施 DevOps 的准入条件。
+4. [探索可行方案](https://devops.phodal.com/manual#探索可行方案)。即 MVP 尝试
+5. [MVP](https://devops.phodal.com/manual#mvp)。一次快速的 DevOps 过程和结果的 showcase。
+6. [精细化 DevOps 实施](https://devops.phodal.com/manual#实施落地)
+7. [回顾优化](https://devops.phodal.com/manual#回顾优化)
+8. [规模化 DevOps 落地](https://devops.phodal.com/manual#规模化)
+
+
+
+对于技术债务,它的利息表现为系统的不稳定性,以及由于临时性手段和缺乏合适的设计、文档工作和测试带来的不断攀升的维护成本。 —— 《架构师应该知道的 97 件事》
+

+ 161 - 0
source/_posts/Docker 一点点.md

@@ -0,0 +1,161 @@
+title: Docker 一点点
+author: Gamehu
+tags:
+
+  - Docker
+categories:
+  - 工作
+date: 2019-11-26 15:32:00
+
+---
+
+### 背景
+
+由于我们产品是基于docker做的部署,所以不管在开发过程中还是在处理客户现场问题时,多多少少都要用到一些docker命令,此篇做个简单的记录,把我用到的命令记录下来。
+
+### 先看图
+
+说命令之前先看图了解下便于更有代入感。
+
+**架构图**(不包含Dokcer Engine等细节)
+
+{% asset_img architecture.png docs.docker.com %}
+
+{% asset_img docker-arch1.jpg 运维之美 -www.hi-linux.com %}
+
+### 命令
+
+#### 各种查看
+
+##### `docker COMMAND --help`
+
+查看docker相关命令的信息,里面有每个命令的说明。
+
+##### `docker ps、docker ps -a`
+
+docker ps 这是最常用的,查看容器的运行状态,查问题时不ps一下心里都没底,该命令会列出所有正在运行的容器,当然 等同于docker container ls。
+
+另外docker ps -a,可用于显示所有正在运行和退出的容器。
+
+##### `docker info、docker version`
+
+docker info 该命令用于获取当前安装的docker版本以及有关操作系统的几条信息。
+
+{% asset_img 1.png %}
+
+docker version 列出有关Docker客户端和服务器版本的信息。
+
+```
+Client:
+ Version:           18.09.7
+ API version:       1.39
+ Go version:        go1.10.1
+ Git commit:        2d0083d
+ Built:             Fri Aug 16 14:20:06 2019
+ OS/Arch:           linux/amd64
+ Experimental:      false
+
+Server:
+ Engine:
+  Version:          18.09.7
+  API version:      1.39 (minimum version 1.12)
+  Go version:       go1.10.1
+  Git commit:       2d0083d
+  Built:            Wed Aug 14 19:41:23 2019
+  OS/Arch:          linux/amd64
+  Experimental:     false
+```
+
+##### `docker search xxx`
+
+该命令只有在我自己玩得时候用过(不想重复造轮子),搜索registry上得镜像。
+
+##### `docker images`
+
+ 列出所有的镜像,通常只需要关注REPOSITORY、TAG两列就行。
+
+```
+root@feature1_dev:~# docker images
+REPOSITORY                                     TAG                                  IMAGE ID            CREATED             SIZE
+172.17.162.141:5000/baymax-nginx               1.17.6                               231d40e811cd        6 months ago        126MB
+172.17.162.141:5000/pg10-cmdb                  1.3.0                                284de991364f        10 months ago       370MB
+172.17.162.141:5000/myflink                    1.8.1                                96c4d2af10fc        10 months ago       449MB
+172.17.162.141:5000/yandex/clickhouse-server   19                                   58006c9044b7        13 months ago       514MB
+172.17.162.141:5000/zookeeper                  latest                               f336949ce7a1        19 months ago       148MB
+172.17.162.141:5000/redis                      latest                               1babb1dde7e1        20 months ago       94.9MB
+172.17.162.141:5000/kafka                      latest                               568143d73a6b        20 months ago       339MB
+172.17.162.141:5000/dubbo-admin                latest                               954bf5f29e96        2 years ago         492MB
+
+```
+
+##### `docker logs -f container_name `
+
+查看容器的日志,我用的也较少。
+
+#####  `docker commit -a "gamehu" -m "what f" container_id ` IMAGE_REPOSITORY:TAG`
+
+通过容器id创建一个新的镜像,
+
+#### Container
+
+##### `docker start 、stop、restart、rm、kill` 
+
+高频使用了,后接 container_id/container_name,依次分别为:启动(已存在)容器、停止容器(会进行正常时间等待其停止)、重启重启、删除(已停止)容器、立即停止容器
+
+#####  `docker exec -it container_id`  
+
+使用的较多,通常是为了测试而替换容器内的内容,命令用于访问正在运行的容器,并启用交互模式,可用一些基本的命令。
+
+```
+root@feature1_dev:~# docker exec -it 58f5d79c10a3 /bin/bash
+root@58f5d79c10a3:/# ls
+bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
+root@58f5d79c10a3:/#
+```
+
+##### `docker inspect container_id` 
+
+查看容器的相关信息,用的也较少。
+
+#### Image
+
+##### `docker run、create`
+
+基于镜像创建一个新的容器,`run`是创建并启动,`create`是创建但不启动。
+
+示例:`docker  run -i -t -p 1000:8000  image_name/image_id:TAG`,使用镜像,以后台模式启动一个容器,将容器的 8000 端口映射到主机的 1000 端口
+
+##### `docker build <path to docker file>`
+
+此命令用于从指定的dockerfile构建镜像。
+
+#####  `docker push IMAGE_NAME:TAG`
+
+做完镜像推送到镜像仓库。
+
+##### `docker rmi image_id/image_name`
+
+删除镜像,通常是处理现场问题,要替换镜像的时候用一用。
+
+#####  `docker inspect image_id`
+
+查看镜像相关信息,我制作镜像的时候会用一用,用的很少。
+
+##### `docker save image_id> xx.tar`
+
+导出镜像,通常是修复现场问题时做该操作,导出已修复的镜像。
+
+##### `docker load < xx.tar`
+
+导入镜像,通常是修复现场问题时做该操作,载入已修复后的镜像。
+
+##### `docker tag image_id tag_name`
+
+修改镜像的TAG,通常是修复现场问题时做该操作。
+
+#### 感谢
+
+{% blockquote Jeff Hale https://towardsdatascience.com/15-docker-commands-you-should-know-970ea5203421  15 Docker Commands You Should Know %}
+{% endblockquote %}
+
+`本文引用的内容,如有侵权请联系我删除,给您带来的不便我很抱歉。`

BIN
source/_posts/Docker 一点点/1.png


BIN
source/_posts/Docker 一点点/architecture.png


BIN
source/_posts/Docker 一点点/docker-arch1.jpg


+ 264 - 0
source/_posts/ES Module.md

@@ -0,0 +1,264 @@
+title: ES Module
+author: Gamehu
+tags:
+  - ES Module
+categories:
+  - 前端
+date: 2020-02-23 22:33:00
+
+---
+
+单独记录一下ES Module,听得太多用的也多,但是一直没深刻的认识一下它。
+
+同样的节奏先Google找是否有大佬写这方面的文章。
+
+幸运的是被我找到了[Lin Clark](https://twitter.com/linclark)(之前我学习浏览器方面的知识就是读的她的文章)写的,很喜欢她的文章,讲的很生动和具体。
+
+### 开始
+
+来来来,搬运一下这一篇[ES modules: A cartoon deep-dive](https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/)。
+
+#### 模块如何提供帮助?
+
+模块为您提供了更好的方式来组织这些变量和函数。使用模块,您可以将有意义的变量和函数组合在一起。
+
+这会将这些函数和变量放入模块范围。模块作用域可用于在模块中的功能之间共享变量。
+
+但是与函数作用域不同,模块作用域具有一种使其变量也可用于其他模块的方式。他们可以明确地说出模块中的哪些变量,类或函数应该可用。
+
+当其他模块可以使用某些东西时,这称为导出。导出后,其他模块可以明确地说它们依赖于该变量,类或函数。
+
+{% asset_img 1.png %}
+
+因为这是一种明确的关系,所以您可以知道如果删除另一个模块,哪个模块将中断。
+
+一旦能够在模块之间导出和导入变量,就可以更轻松地将代码分解为可以相互独立工作的小块。然后,您可以组合并重组这些块(类似于积木),以从同一组模块创建所有不同种类的应用程序。
+
+#### ES模块如何工作
+
+在使用模块进行开发时,您将建立一个依赖关系图。不同依赖项之间的连接来自您使用的任何导入语句。
+
+这些导入语句是浏览器或Node如何确切知道其需要加载哪些代码的方式。您给它一个文件,以用作图形的入口点。从那里开始,它紧随任何import语句以查找其余代码。
+
+[![具有两个依赖关系的模块。 顶部模块是条目。 另外两个使用import语句关联](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/04_import_graph-500x291.png)](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/04_import_graph.png)
+
+但是文件本身不是浏览器可以使用的东西。它需要解析所有这些文件,以将它们转换为称为模块记录的数据结构。这样,它实际上知道文件中正在发生什么。
+
+[![具有各种字段的模块记录,包括RequestedModules和ImportEntries](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/05_module_record-500x287.png)](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/05_module_record.png)
+
+之后,需要将模块记录转换为模块实例。实例结合了两件事:代码和状态。
+
+该代码基本上是一组指令。这就像如何做某食物的食谱。但是就其本身而言,您不能使用该代码执行任何操作。您需要原材料才能与这些代码一起使用。
+
+什么是状态?就像做食物的原材料。状态是变量在任何时间点的实际值。当然,这些变量只是内存中保存值的空间的昵称。
+
+因此,模块实例将代码(指令列表)与状态(所有变量的值)组合在一起。
+
+[![结合了代码和状态的模块实例](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/06_module_instance-500x372.png)](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/06_module_instance.png)
+
+我们需要的是每个模块的模块实例。模块加载的过程将从此入口点文件变为具有模块实例的完整图。
+
+对于ES模块,这分为三个步骤。
+
+1. 构造—查找,下载所有文件并将其解析为模块记录。
+2. 实例化—查找内存中的空间以放置所有导出的值(但尚未用值填充它们)。然后使导出和导入都指向内存中的那些空间的位置(地址)。这称为链接(引用)。
+3. 求值—运行代码以将变量的实际值填写在对应的内存空间。
+
+[![三个阶段。 构建从单个JS文件到多个模块记录。 实例化链接那些记录。 评估执行代码。](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/07_3_phases-500x184.png)](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/07_3_phases.png)
+
+人们谈论ES模块是异步的。您可以将其视为异步的,因为工作分为三个不同的阶段(加载,实例化和评估),并且这些阶段可以分别完成。
+
+这意味着规范确实引入了CommonJS中不存在的一种异步。我将在后面解释,但是在CommonJS中,模块及其下面的依赖项一次全部被加载,实例化和求值,而中间没有任何中断。
+
+但是,步骤本身不一定是异步的。它们可以以同步方式完成。这取决于正在执行的加载。这是因为并非所有内容都由ES模块规范控制。实际上有两部分工作,分别由不同的规范涵盖。
+
+在[ES模块规范](https://tc39.github.io/ecma262/#sec-modules)说,你应该如何解析文件到模块的记录,你应该如何实例化和评估模块。但是,它并没有说明如何首先获取文件。
+
+加载程序将获取文件。加载程序在其他规范中指定。对于浏览器,该规范是[HTML规范](https://html.spec.whatwg.org/#fetch-a-module-script-tree)。但是您可以根据所使用的平台使用不同的装载程序。
+
+[![两个卡通人物。 一个代表说明如何加载模块的规范(即HTML规范)。 另一个代表ES模块规范。](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/07_loader_vs_es-500x286.png)](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/07_loader_vs_es.png)
+
+加载程序还精确控制模块的加载方式。它调用ES模块的方法- `ParseModule`,`Module.Instantiate`和`Module.Evaluate`。有点像操纵JS引擎的字符串的p。
+
+[![加载程序图形充当ES模块规范图形的伪造者。](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/08_loader_as_puppeteer-500x330.png)](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/08_loader_as_puppeteer.png)
+
+现在,让我们详细介绍每个步骤。
+
+#### 构建
+
+在构建阶段,每个模块发生三件事。
+
+1. 找出从哪里下载包含模块的文件
+2. 提取文件(通过从URL下载文件或从文件系统加载文件)
+3. 将文件解析为模块记录
+
+#### 查找并获取文件
+
+加载程序将负责查找文件并下载。首先,它需要找到入口点文件。在HTML中,您可以通过脚本标记告诉加载程序在哪里找到它。
+
+[![具有type = module属性和src URL的脚本标记。 src URL有一个文件,它是条目](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/08_script_entry-500x188.png)](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/08_script_entry.png)
+
+但是,如何找到下一组模块- `main.js`直接依赖的模块呢?
+
+这就是导入语句的来源。导入语句的一部分称为模块说明符。它告诉加载程序可以在哪里找到每个下一个模块。
+
+{% asset_img 2.png %}
+
+有关模块说明符的一件事:在浏览器和Node之间有时需要对它们进行不同的处理。每个主机都有自己的解释模块说明符字符串的方式。为此,它使用一种称为模块解析算法的模块,该算法在平台之间有所不同。当前,某些可在Node中工作的模块说明符在浏览器中将无法工作,但[仍在进行修复](https://github.com/domenic/package-name-maps)。
+
+在此问题修复之前,浏览器仅接受URL作为模块说明符。他们将从该URL加载模块文件。但这不会同时出现在整个图表上。在解析文件之前,您不知道模块需要获取哪些依赖项,并且在获取文件之前无法解析文件。
+
+这意味着我们必须逐层遍历该树,解析一个文件,然后找出其依赖项,然后查找并加载这些依赖项。
+
+{% asset_img 3.png %}
+
+如果主线程要等待这些文件中的每一个下载,则许多其他任务将堆积在其队列中。
+
+{% asset_img 4.png %}
+
+这样阻塞主线程会使使用模块的应用程序使用起来太慢。这是ES模块规范将算法分为多个阶段的原因之一。将构造分为自己的阶段,使浏览器可以在开始实例化的同步工作之前获取文件并增强对模块图的理解。
+
+这种方法(算法分为多个阶段)是ES模块和CommonJS模块之间的主要区别之一。
+
+CommonJS可以做不同的事情,因为从文件系统加载文件比通过Internet下载花费的时间少得多。这意味着Node可以在加载文件时阻止主线程。并且由于文件已经加载,因此仅实例化和求值(在CommonJS中不是单独的阶段)是有意义的。这也意味着在返回模块实例之前,您要遍历整棵树,加载,实例化和评估任何依赖项。
+
+{% asset_img 5.png %}
+
+CommonJS方法有一些含义,我将在后面详细解释。但是,这意味着一件事,就是在带有CommonJS模块的Node中,可以在模块说明符中使用变量。`require`在寻找下一个模块之前,您正在执行该模块中的所有代码(直到语句)。这意味着当您进行模块解析时,变量将具有一个值。
+
+但是,使用ES模块,您可以在进行任何计算(求值)之前预先建立整个模块图。这意味着您不能在模块说明符中包含变量,因为这些变量尚无值。
+
+{% asset_img 6.png %}
+
+但是有时将变量用于模块路径确实很有用。例如,您可能想根据代码在做什么或在什么环境中运行来切换加载的模块。
+
+为了使ES模块成为可能,有一个建议叫做[动态导入](https://github.com/tc39/proposal-dynamic-import)。有了它,您可以使用类似的导入语句`import(`${path}/foo.js`)`。
+
+动态导入的工作原理是,任何使用`import()`来导入的文件,都会作为一个入口文件从而创建一棵单独的依赖树,被单独处理。
+
+{% asset_img 7.png %}
+
+但是要注意一件事–这两棵树中的任何模块都将共享一个模块实例。这是因为加载程序会缓存模块实例。对于特定全局范围内的每个模块,将只有一个模块实例。
+
+这意味着浏览器的工作量更少。例如,这意味着即使多个模块依赖该模块文件,该模块文件也只会被提取一次。(这是缓存模块的一个原因。我们将在评估部分中看到另一个原因。)
+
+加载程序使用称为[模块映射的内容](https://html.spec.whatwg.org/multipage/webappapis.html#module-map)来管理此缓存。每个全局变量在单独的模块图中跟踪其模块。
+
+当加载程序获取一个URL时,它将把该URL放入模块映射中,并记下它当前正在获取文件。然后它将发出请求并继续以开始获取下一个文件。
+
+{% asset_img 8.png %}
+
+如果另一个模块依赖于同一文件会怎样?加载程序将在模块映射中查找每个URL。如果在其中看到`fetching`,它将继续前进到下一个URL。
+
+但是模块图不仅跟踪正在获取的文件。模块映射还充当模块的缓存,如下所示。
+
+#### 解析
+
+现在我们已经获取了该文件,我们需要将其解析为模块记录。这有助于浏览器了解模块的不同部分。
+
+[![该图显示了被解析成模块记录的main.js文件](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/25_file_to_module_record-500x199.png)](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/25_file_to_module_record.png)
+
+创建模块记录后,将其放置在模块映射中。这意味着无论何时从此处请求,加载程序都可以将其从该映射中拉出。
+
+[![模块映射图中的“获取”占位符被模块记录填充](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/25_module_map-500x239.png)](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/25_module_map.png)
+
+解析有一个细节看似微不足道,但实际上有很大的含义。所有模块都像**严格模式**来解析的。也还有其他的小细节,比如,关键字 `await` 在模块的最顶层是保留字, `this` 的值为 `undefinded`。
+
+这种不同的解析方式称为“解析目标”。如果您解析相同的文件但使用不同的目标,那么最终将得到不同的结果。因此,在开始解析之前就需要知道要解析的文件类型,不管是否是模块。
+
+在浏览器中,这非常简单。您只需放入`type="module"`script标签。这告诉浏览器应将此文件解析为模块。并且由于只能导入模块,因此浏览器知道任何导入也是模块。
+
+[![加载程序确定main.js是一个模块,因为script标签上的type属性表明是这样,而counter.js必须是一个模块,因为它已导入](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/26_parse_goal-500x311.png)](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/26_parse_goal.png)
+
+但是在Node中,您不使用HTML标记,因此无法选择使用`type`属性。社区尝试解决此问题的一种方法是使用 `.mjs`扩展。使用该扩展名告诉Node,“此文件是一个模块”。您会看到人们将其视为解析目标的信号。目前讨论仍在进行中,因此尚不清楚Node社区最终决定使用什么信号。
+
+无论哪种方式,加载程序都将确定是否将文件解析为模块。如果它是一个模块并且有imports,它将重新开始该过程,直到提取并解析了所有文件。
+
+在加载过程的最后,您已经从只有一个入口点文件变成了拥有许多模块记录。
+
+[![建设阶段的结果,左侧为JS文件,右侧为3个已解析的模块记录](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/27_construction-500x406.png)](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/27_construction.png)
+
+下一步是实例化此模块并将所有实例连接在一起。
+
+#### 实例化
+
+就像我之前提到的,实例化是将代码与状态结合在一起。该状态存在于内存中,因此实例化步骤就是将所有状态链接到内存。
+
+首先,JS引擎创建一个**模块环境记录**(Module Environment Record)。它是管理所有模块记录的变量。然后,它会在内存中找到所有export对应的的地址。模块环境记录将跟踪内存中与每个export相关联的地址。
+
+内存中的这些地址对应的空间尚无法获取其值。只有在运行之后,它们的实际值才会被填写。需要注意的一点是:在此阶段中将初始化所有导出的函数声明。这将使后面的执行阶段变得更加容易。
+
+为了实例化**模块关系图**,引擎会采用**深度优先的后序遍历方式**。这意味着它将到达关系图的最底部(底部不依赖于其他任何东西),并设置其导出。
+
+{% asset_img 9.png %}
+
+最终,引擎会把模块下的所有依赖导出连接到当前模块。接着回到上一层把模块的导入连接起来。
+
+请注意,导出和导入均指向内存中的同一位置。
+
+{% asset_img 10.png %}
+
+这不同于CommonJS模块。在CommonJS中,整个导出对象在导出时被复制。这意味着导出的任何值(如数字)都是副本,所以在CommonJS如果导出模块以后更改了该值,则导入模块将看不到该更改。
+
+这意味着,如果导出模块以后更改了该值,则导入模块将看不到该更改。
+
+{% asset_img 11.png %}
+
+相反,ES模块使用**实时绑定**(Live Binding)。两个模块都指向内存中的相同位置(引用)。这意味着,当导出模块更改值时,该更改将显示在导入模块中。
+
+导出值的模块可以随时更改这些值,但是导入模块不能更改其导入的值,因为是导入的是**只读引用**。不过如果模块导入了一个对象,则它可以更改该对象上的属性值。
+
+{% asset_img 12.png %}
+
+之所以ESM采用实时绑定,是因为可以在不运行任何代码的情况下链接到所有模块。这有助于解决循环依赖的问题,在后面的运行(evaluation)阶段会细说。
+
+OK,当实例化结束时,我们得到了所有模块实例,并知道了已完成链接的导出/导入变量的内存地址。
+
+现在我们可以开始评估代码,并使用它们的值填充这些内存位置。
+
+#### 运行
+
+最后一步是往解析阶段获取的内存地址所在的空间里填充值。JS 引擎通过运行顶层代码(函数外的代码)来完成填充。
+
+除了填充值以外,运行代码还可能引发副作用。例如,一个模块可能会请求服务器。
+
+[![模块将在功能之外进行编码,标记为顶级代码](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/40_top_level_code-500x146.png)](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/40_top_level_code.png)
+
+因为这些潜在副作用的存在,所以**模块代码只能运行一次**。
+前面我们看到,实例化阶段中发生的链接过程可以多次进行,并且每次的结果都一样。但是,如果运行阶段进行多次的话,则可能会每次都得到不一样的结果。
+
+这正是为什么需要有模块映射的原因之一。模块映射通过规范URL,缓存模块,因此每个模块只有一个模块记录。这样可以确保每个模块仅执行一次。与实例化一样,这是深度优先的后遍历。
+
+那我们之前谈到的循环依赖怎么处理呢?
+
+在循环依赖关系中,您最终会在模块关系图中出现循环。你依赖我我依赖你,通常,这会变成很大的循环。
+
+为了解释这个问题,我举个例子。
+
+ {% asset_img 13.png %}
+
+首先让我们看一下如果时CommonJS模块会时什么样的。首先,main模块将执行到require语句。然后它将去加载counter模块。
+
+ {% asset_img 14.png %}
+
+然后,counter模块将尝试从访问导出的对象`message`。但是由于尚未在main模块中执行,因此它将返回undefined。JS引擎将在内存中为局部变量分配空间,并将该值设置为undefined。
+
+[![中间的内存,main.js和内存之间没有连接,但是从counter.js到未定义的内存位置的导入链接](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/42_cjs_variable_2-500x113.png)](https://2r4s9p1yi1fa2jd7j43zph8r-wpengine.netdna-ssl.com/files/2018/03/42_cjs_variable_2.png)
+
+此时会一直运行持续到counter模块顶级代码的末尾。我们想看看是否最终将获得正确的message(在执行main.js之后),因此我们设置了超时时间。然后继续运行到`main.js`。
+
+ {% asset_img 15.png %}
+
+message变量将被初始化并添加到内存中。但是由于两者之间没有连接,因此message在counter模块中仍然是时undefined。
+
+ {% asset_img 16.png %}
+
+如果使用实时绑定处理导出,则counter模块最终将看到正确的值。到超时运行时,`main.js`的执行就已经完成并填充了值。
+
+支持循环依赖是 ESM 设计之初就考虑到的一大因素。也正是这种分(三)阶段设计使其成为可能。
+
+#### 原文地址:
+
+{% blockquote Lin Clark  https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/  ES modules: A cartoon deep-dive %}
+
+{% endblockquote %}

BIN
source/_posts/ES Module/1.png


BIN
source/_posts/ES Module/10.png


BIN
source/_posts/ES Module/11.png


BIN
source/_posts/ES Module/12.png


BIN
source/_posts/ES Module/13.png


BIN
source/_posts/ES Module/14.png


BIN
source/_posts/ES Module/15.png


BIN
source/_posts/ES Module/16.png


BIN
source/_posts/ES Module/2.png


BIN
source/_posts/ES Module/3.png


BIN
source/_posts/ES Module/4.png


BIN
source/_posts/ES Module/5.png


BIN
source/_posts/ES Module/6.png


BIN
source/_posts/ES Module/7.png


BIN
source/_posts/ES Module/8.png


BIN
source/_posts/ES Module/9.png


+ 217 - 0
source/_posts/ES2020-2021.md

@@ -0,0 +1,217 @@
+title: ES2020/2021
+author: Gamehu
+tags:
+  - 前端
+categories:
+  - 学习
+date: 2021-07-09 10:42:00
+---
+### 背景
+
+今天看阮老师的科技周刊的时候,里头提到了ES2021(作者默认所有的提案最终都会被通过),正好借此梳理一下,ES2020和ES2021,个人使用过的以及后续可能会使用的一些功能,所以这篇不是科普类型,纯属个人喜好的记录。
+
+### 开始
+
+##### 空值合并运算符:??
+
+> **??**是一个逻辑操作符,当左侧的操作数为 [`null`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/null) 或者 [`undefined`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/undefined) 时,则返回右侧操作数,否则返回左侧操作数。所以该运算符完美适配默认值的场景。
+
+```javascript
+const foo = null ?? 'default string';
+console.log(foo);
+// expected output: "default string"
+
+const baz = 0 ?? 42;
+console.log(baz);
+// expected output: 0
+```
+
+多说一句:
+
+> 设置默认值以前常用的是:**||**(逻辑或操作符),但是都知道不用用它作为有false和0的情况(因为||**判断时,会把值转换为布尔值,而false和0转为布尔值时都是false,所以对于数字类型和布尔类型的用||设置默认值是不合理的+)
+
+
+
+
+
+##### 可选的链接运算符:?. 
+
+> 嵌套对象时特别好用。表达式还短。
+>
+> 如果引用为空(null 或 undefined),则表达式会短路返回 undefined。
+
+```javascript
+
+if( a && a.b  && a.b.c){
+    //do something...
+}
+//可换成:
+if( a?.b?c){
+    //do something...
+}
+
+
+const a={}
+const test=a?.b?.c
+// expected output: undefined
+```
+
+##### Promise.any() and AggregateError
+
+`Promise.any()`方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只要参数实例有一个变成`fulfilled`状态,包装实例就会变成`fulfilled`状态;如果所有参数实例都变成`rejected`状态,包装实例就会变成`rejected`状态
+
+[阮一峰 ECMAScript 6 (ES6) 标准入门教程 第三版](https://www.bookstack.cn/read/es6-3rd/spilt.9.docs-promise.md)
+
+[Promise.race和Promise.any](https://stackoverflow.com/questions/61732049/what-is-the-difference-between-promise-any-and-promise-race)
+
+`Promise.any()`跟`Promise.race()`方法很像,只有一点不同,就是不会因为某个 Promise 变成`rejected`状态而结束。
+
+```javascript
+Promise.race([
+  new Promise((resolve, reject) => setTimeout(reject, 200, 'Third')),
+  new Promise((resolve, reject) => setTimeout(resolve, 1000, 'Second')),
+  new Promise((resolve, reject) => setTimeout(resolve, 2000, 'First')),
+])
+.then(value => console.log(`Result: ${value}`))
+.catch (err => console.log(err))
+// expected output: Third
+
+
+Promise.any([
+  new Promise((resolve, reject) => setTimeout(reject, 200, 'Third')),
+  new Promise((resolve, reject) => setTimeout(resolve, 1000, 'Second')),
+  new Promise((resolve, reject) => setTimeout(resolve, 2000, 'First')),
+])
+.then(value => console.log(`Result: ${value}`))
+.catch (err => console.log(err))
+// expected output: Second
+```
+
+##### globalThis
+
+全局属性 [`globalThis`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/globalThis) 包含全局的 `this` 值,类似于全局对象(global object)。`globalThis` 提供了一个标准的方式来获取不同环境下的全局 `this` 对象(也就是全局对象自身)不用在考虑不同的环境获取方式不一样的问题。
+
+
+
+##### String replaceAll()
+
+```
+const newStr = str.replaceAll(regexp|substr, newSubstr|function).
+// 当使用一个 `regex`时,您必须设置全局(“ g”)标志
+```
+
+**`replaceAll(pattern,replacement)`** 方法返回一个新字符串,新字符串所有满足 `pattern` 的部分都已被`replacement` 替换。`pattern`可以是一个字符串或一个 [`RegExp`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp), `replacement`可以是一个字符串或一个在每次匹配被调用的函数。
+
+ **old:**
+
+```javascript
+const str = "zhangsan is wangmazi's 舅子,wangmazi is zhangsan's 妹夫";
+const newStr = str.replace("is", "isn't");
+console.log(newStr); 
+// expected output:zhangsan isn't wangmazi's 舅子,wangmazi is zhangsan's 妹夫
+
+// 替换所有,只能用正则
+const newStr = str.replace(/is/g, "isn't");
+console.log(newStr);
+//expected output: zhangsan isn't wangmazi's 舅子,wangmazi isn't zhangsan's 妹夫
+```
+
+**new:**
+
+```javascript
+const str = "zhangsan is wangmazi's 舅子,wangmazi is zhangsan's 妹夫";
+const newStr = str.replaceAll("is", "isn't");
+console.log(newStr); 
+// expected output: zhangsan isn't wangmazi's 舅子,wangmazi isn't zhangsan's 妹夫
+```
+
+
+
+##### 逻辑赋值运算符:(&&= ||= ??=)
+
+```javascript
+x ||= y;
+// 等同
+x || (x = y);
+ 
+x &&= y;
+// 等同
+x && (x = y); 
+// 或者
+if(x) {
+  x = y
+}
+ 
+x ??= y;
+// 等同
+x ?? (x = y);
+
+
+// 比如
+let x = 1;
+let y = 2;
+x &&= y;
+console.log(x); 
+//expected output: 2
+ 
+```
+
+##### 下划线作为数字分隔符
+
+```javascript
+const billion = 1000_000_000;
+console.log(billion); 
+//expected output:1000000000
+const trillion = 1000_000_000_000n;
+console.log(trillion.toString()); 
+//expected output: "1000000000000"
+console.log(1000_000_000 === 1000000000); 
+//expected output: true
+```
+
+[了解更多](https://backbencher.dev/javascript/numeric-separators)
+
+##### Promise.allSettled
+
+我通常在页面初始化需要多个数据且相互之间又没联系的时候会用它。
+
+> **Promise.allSettled()**方法接受一组Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果(不管是`fulfilled`还是`rejected`),返回结果是一个对象数组,每个对象表示对应的promise结果。
+>
+> 当有多个彼此不依赖的异步任务成功完成时,或者我们不关心异步操作的结果,只关心每个`promise`的结果时,通常使用它。
+
+```javascript
+const p1 = new Promise((resolve, reject) => setTimeout(resolve, 1000,'failed'));
+const p2 = new Promise((resolve, reject) => setTimeout(reject, 2000,'a'));
+const p3 = new Promise((resolve, reject) => setTimeout(resolve, 3000,'b'));
+// 返回值对象:fulfilled时,对象有value属性,rejected时有reason属性
+Promise.allSettled([p1, p2, p3]).then(values => console.log(values));
+
+//expected output: Array
+// 0: {status: "fulfilled", value: "failed"}
+// 1: {status: "rejected", reason: "a"}
+// 2: {status: "fulfilled", value: "b"}
+```
+
+> 相比之下,`Promise.all()` 更适合彼此相互依赖或者在其中任何一个`reject`时就需要立即结束的场景。即`Promise.all()` 其实无法确定所有请求都结束。
+
+
+
+#### 参考资料:
+
+https://github.com/tc39/ecma262/releases
+
+https://backbencher.dev/javascript/es2021-new-features
+
+https://mp.weixin.qq.com/s?__biz=MzUxMzcxMzE5Ng==&mid=2247494289&idx=2&sn=d8a0ef1443954b7a5bae79ec90411cbd&chksm=f9525fd2ce25d6c4f1d1ac2ab8ce6b7034f68f484881a3548549648dfe5aedd427c7b930385b&scene=21#wechat_redirect
+
+https://tc39.es/ecma262/2021/#sec-web-scripting
+
+
+https://www.telerik.com/blogs/learn-new-features-introduced-javascript-es2021
+
+https://blog.fundebug.com/2019/08/28/javascript-nullish-coalescing/
+
+
+
+`本文引用的内容,如有侵权请联系我删除,给您带来的不便我很抱歉。`
+

+ 45 - 0
source/_posts/ESLint-no-prototype-builtins.md

@@ -0,0 +1,45 @@
+title: ESLint(no-prototype-builtins)
+author: Gamehu
+tags:
+  - ESLint
+categories:
+  - 前端
+date: 2020-11-24 14:56:00
+
+---
+
+  // eslint-disable-next-line no-prototype-builtins
+
+​    if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) return 0;
+
+
+
+[no-prototype-builtins - Rules - ESLint - Pluggable JavaScript linter](https://eslint.org/docs/rules/no-prototype-builtins)
+
+## Rule Details
+
+This rule disallows calling some `Object.prototype` methods directly on object instances.
+
+Examples of **incorrect** code for this rule:
+
+```
+/*eslint no-prototype-builtins: "error"*/
+
+var hasBarProperty = foo.hasOwnProperty("bar");
+
+var isPrototypeOfBar = foo.isPrototypeOf(bar);
+
+var barIsEnumerable = foo.propertyIsEnumerable("bar");
+```
+
+Examples of **correct** code for this rule:
+
+```
+/*eslint no-prototype-builtins: "error"*/
+
+var hasBarProperty = Object.prototype.hasOwnProperty.call(foo, "bar");
+
+var isPrototypeOfBar = Object.prototype.isPrototypeOf.call(foo, bar);
+
+var barIsEnumerable = {}.propertyIsEnumerable.call(foo, "bar");
+```

+ 193 - 0
source/_posts/ETL复习(1).md

@@ -0,0 +1,193 @@
+title: ETL复习(1)
+author: Gamehu
+tags:
+  - ETL
+categories:
+  - 学习
+date: 2025-03-07 22:36:00
+---
+<div class="tag-container">
+  <span class="main-tag">面试知识梳理</span>
+  <span class="sub-tag">第一篇</span>
+</div>
+
+# 背景
+
+最近找工作,有些大数据岗位我想投,但是奈何之前的工作内容大数据不是主业,大数据经验不够看,我最早要追溯到15年当时spark+hive,然后17年的storm+hbase,到最近的flink+ck,我觉得我努把力看能不能够一够大数据相关的岗位。
+
+## 基础环境准备
+
+把我给媳妇儿配的打LOL的电脑,偷偷拿来用一用,当成小型服务器,反正性能对LOL来说,很过剩了,不影响。
+
+我之前鼓捣其它技术的时候就在电脑上装了虚拟机,所以也不折腾了,直接装个ubuntu,然后装个docker+docker compose,就差不多了。
+
+### docker镜像源
+
+单独说下,因为docker默认用的国外的镜像源所以安装后几乎是不可用的,这时候需要配置国内的镜像。
+要注意验证镜像源,比如通过curl等命令,看是否能正常访问是否能免验证访问,我就是被阿里云的镜像加速器耽搁了小半小时,就是按照官方的配置始终403,最后才发现,原理阿里前几个月更新了协议,大概意思是,不再支持外部直接用加速镜像,而是支持阿里云本身的产品使用。
+
+{% codeblock  %}
+      # 1. 验证镜像源
+      curl 镜像源 
+      # 2. 添加镜像源
+      sudo mkdir -p /etc/docker
+      sudo tee /etc/docker/daemon.json <<-'EOF'
+      {
+        "registry-mirrors": [
+          "https://xxxx"
+        ]
+      }
+      EOF
+      
+      # 3. 使其生效
+      sudo systemctl daemon-reload
+      sudo systemctl restart docker
+
+      # 4. 查看镜像是否修改成功
+      docker info
+
+      # 5. 拉取镜像验证
+      docker pull xxx
+       {% endcodeblock %}
+
+### 安装CK
+{% codeblock  %}
+      # 1. 获取ck镜像
+       docker pull clickhouse/clickhouse-server
+      # 2. 添加ck需要的目录
+      mkdir -p /data/clickhouse/data /data/clickhouse/config /data/clickhouse/logs
+      
+      # 3. ck的配置
+      cat > /data/clickhouse/config/config.xml << EOF
+        <?xml version="1.0"?>
+        <yandex>
+            <logger>
+                <level>information</level>
+                <log>/var/log/clickhouse-server/clickhouse-server.log</log>
+                <errorlog>/var/log/clickhouse-server/clickhouse-server.err.log</errorlog>
+            </logger>
+
+            <http_port>8123</http_port>
+            <tcp_port>9000</tcp_port>
+            <interserver_http_port>9009</interserver_http_port>
+            
+            <listen_host>0.0.0.0</listen_host>
+            
+            <max_connections>4096</max_connections>
+            <keep_alive_timeout>10</keep_alive_timeout>
+            <max_concurrent_queries>100</max_concurrent_queries>
+            <uncompressed_cache_size>8589934592</uncompressed_cache_size>
+            <mark_cache_size>5368709120</mark_cache_size>
+            
+            <path>/var/lib/clickhouse/</path>
+            <tmp_path>/var/lib/clickhouse/tmp/</tmp_path>
+            
+            <user_directories>
+                <users_xml>
+                    <path>/etc/clickhouse-server/users.xml</path>
+                </users_xml>
+            </user_directories>
+
+            <timezone>UTC</timezone>
+        </yandex>
+        EOF
+
+      # 4. ck用户管理
+          cat > /data/clickhouse/config/users.xml << EOF
+            <?xml version="1.0"?>
+            <yandex>
+                <users>
+                    <default>
+                        <password>yourpassword</password>
+                        <networks>
+                            <ip>::/0</ip>
+                        </networks>
+                        <profile>default</profile>
+                        <quota>default</quota>
+                    </default>
+                </users>
+
+                <profiles>
+                    <default>
+                        <max_memory_usage>10000000000</max_memory_usage>
+                        <use_uncompressed_cache>0</use_uncompressed_cache>
+                        <load_balancing>random</load_balancing>
+                    </default>
+                </profiles>
+
+                <quotas>
+                    <default>
+                        <interval>
+                            <duration>3600</duration>
+                            <queries>0</queries>
+                            <errors>0</errors>
+                            <result_rows>0</result_rows>
+                            <read_rows>0</read_rows>
+                            <execution_time>0</execution_time>
+                        </interval>
+                    </default>
+                </quotas>
+            </yandex>
+            EOF
+
+      # 5.运行容器
+
+      docker run -d \
+        --name clickhouse-server \
+        --ulimit nofile=262144:262144 \
+        -p 8123:8123 \
+        -p 9000:9000 \
+        -p 9009:9009 \
+        -v /data/clickhouse/data:/var/lib/clickhouse \
+        -v /data/clickhouse/config/config.xml:/etc/clickhouse-server/config.xml \
+        -v /data/clickhouse/config/users.xml:/etc/clickhouse-server/users.xml \
+        -v /data/clickhouse/logs:/var/log/clickhouse-server \
+        --restart=always \
+        clickhouse/clickhouse-server:latest
+
+      # 6. 测试是否可用(内部)
+        docker exec -it clickhouse-server clickhouse-client --password yourpassword
+
+      # 7.暴露到外部可访问,由于不想每次run都写一长串,也为了后续方便管理其它容器,把docker compose装上
+        apt update
+        apt install -y docker-compose
+      # 8.compose文件编写,别忘了暴露environment
+        nano /data/clickhouse/docker-compose.yml
+        
+        version: '3'
+          services:
+            clickhouse:
+              image: clickhouse/clickhouse-server:latest
+              container_name: clickhouse-server
+              restart: always
+              ports:
+                - "8123:8123"
+                - "9000:9000"
+                - "9009:9009"
+              volumes:
+                - /data/clickhouse/data:/var/lib/clickhouse
+                - /data/clickhouse/config/config.xml:/etc/clickhouse-server/config.xml
+                - /data/clickhouse/config/users.xml:/etc/clickhouse-server/users.xml
+                - /data/clickhouse/logs:/var/log/clickhouse-server
+              environment:
+                - CLICKHOUSE_USER=default
+                - CLICKHOUSE_PASSWORD=xxxx
+              ulimits:
+                nofile:
+                  soft: 262144
+                  hard: 262144
+      # 删除ck容器后重启
+        cd /data/clickhouse
+        docker-compose up -d
+      # 9. 看是否正常返回
+        curl "http://xx:8123/?user=default&password=xx&query=SELECT%201"
+
+       {% endcodeblock %}
+
+## 还有待续....
+
+# 参考
+https://www.coderjia.cn/archives/dba3f94c-a021-468a-8ac6-e840f85867ea
+https://hub.docker.com/r/clickhouse/clickhouse-server/
+
+

+ 15 - 0
source/_posts/Event-loops.md

@@ -0,0 +1,15 @@
+title: Event loops
+author: Gamehu
+tags:
+  - Event loops
+categories:
+  - 浏览器
+date: 2021-07-19 16:35:00
+---
+https://html.spec.whatwg.org/multipage/webappapis.html#event-loops
+
+
+
+
+
+https://www.w3.org/TR/DOM-Level-3-Events/#event-flow

+ 130 - 0
source/_posts/GC.md

@@ -0,0 +1,130 @@
+title: GC
+author: Gamehu
+date: 2022-06-09 17:12:46
+tags:
+---
+
+### 背景
+
+现场排查OOM,对于GC的一些理解。
+
+### 杂项记录
+
+https://vladmihalcea.com/improve-statement-caching-efficiency-in-clause-parameter-padding/
+
+http://technodibble.blogspot.com/2015/02/hibernate-in-clause-outofmemory.html
+
+
+http://xmlandmore.blogspot.com/2014/10/jdk-8-is-tuning-maxnewsize-in-g1-gc.html
+
+
+heap内存归还给操作系统:G1GC https://openjdk.org/jeps/346
+
+https://www.youtube.com/watch?v=BTIcja5xcK0
+
+https://www.youtube.com/watch?v=IB7oFVYTOJ0
+
+https://gceasy.io/gc-recommendations/important-g1-gc-arguments.jsp
+https://github.com/Snailclimb/JavaGuide/blob/83efb36fb56d197f2c4b471084b884c6a4f23e37/docs/books/java.md
+
+https://www.douban.com/doulist/2545443/
+
+https://www.baeldung.com/jvm-parameters
+https://blog.csdn.net/myth_g/article/details/119855832
+https://docs.oracle.com/en/java/javase/11/gctuning/introduction-garbage-collection-tuning.html#GUID-326EB4CF-8C8C-4267-8355-21AB04F0D304
+
+https://programmer.ink/think/jvm-series-jvm-tuning-jps-jstat-jmap-jhat-jstack-jinfo.html
+
+https://docs.oracle.com/javase/10/jrockit-hotspot/logging.htm#JRHMG121
+https://confluence.atlassian.com/confkb/unrecognized-jvm-gc-options-when-using-java-11-1002472841.html
+
+https://dzone.com/articles/understanding-garbage-collection-log
+
+
+https://sematext.com/blog/java-garbage-collection-tuning/
+
+
+https://sematext.com/blog/java-garbage-collection-tuning/
+
+https://cloud.tencent.com/developer/article/1811734
+
+
+https://docs.oracle.com/en/java/javase/11/tools/jstat.html#GUID-5F72A7F9-5D5A-4486-8201-E1D1BA8ACCB5
+
+https://www.javatang.com/archives/2017/10/19/51301886.html
+
+https://morioh.com/p/935f204ccc1a
+
+https://dzone.com/articles/jvm-tuning-using-jcmd
+
+https://sematext.com/blog/java-garbage-collection-logs/
+### MAT
+
+dump文件分析用的MAT。
+
+https://zhanglvmeng.gitbooks.io/mat-usage/content/kai-shi-shi-yong/yan-shen-yue-du/shi-yong-mat-de-10-ge-jian-yi.html
+
+### 线程分析
+
+https://geekflare.com/generate-analyze-thread-dumps/
+
+https://blog.fastthread.io/2016/02/22/thread-dump-analysis-pattern-repetitive-strain-injury-rsi/
+
+当应用程序出现性能瓶颈时,大部分线程将开始在有问题的瓶颈区域累积。这些线程将具有相同的堆栈跟踪。因此,每当大量线程表现出相同/重复的堆栈跟踪时,就应该调查这些堆栈跟踪。这可能表示性能问题。
+
+
+以下是一些这样的场景:
+
+* 假设您的 SOR 或外部服务正在变慢,那么大量线程将开始等待其响应。在这种情况下,这些线程将显示相同的堆栈跟踪。
+* 假设一个线程获得了一个锁并且它从未释放,那么在同一执行路径中的其他几个线程将进入阻塞状态,显示相同的堆栈跟踪。
+* 如果循环(for 循环、while 循环、do..while 循环)条件未终止,则执行该循环的多个线程将显示相同的堆栈跟踪。
+  当出现上述任何一种情况时,应用程序的性能和可用性都会受到质疑。
+
+重点关注:Troubleshooting Tools、Monitoring Tools
+https://docs.oracle.com/en/java/javase/11/tools/tools-and-command-reference.html
+
+https://programmer.ink/think/jvm-series-jvm-tuning-jps-jstat-jmap-jhat-jstack-jinfo.html
+
+https://www.hollischuang.com/archives/110
+
+线程状态产生的原因
+
+* runnable:状态一般为RUNNABLE。
+
+* in Object.wait():等待区等待,状态为WAITING或TIMED_WAITING。
+
+* waiting for monitor entry:进入区等待,状态为BLOCKED。
+
+* waiting on condition:等待区等待、被park。
+
+* sleeping:休眠的线程,调用了Thread.sleep()。
+
+https://jakubstransky.com/2017/12/19/hotspot-jvm-internal-threads/
+
+#### Tomcat线程模型
+
+>NIO: synchronous and non blocking. It can support large concurrency better than traditional bio. This mode is adopted by default after Tomcat 8.0.
+
+##### NiO
+
+https://developpaper.com/nio-optimization-principle-and-tomcat-thread-model/
+
+Tomcat’s NiO model has more poller rolesAcceptor、PollerandHandler worker thread pool。 Are these three roles very familiar? If poller is replaced by reactor, is it the reactor model. Yes, Tomcat’s NiO model is based onMaster slave reactor modelIt’s just a change of name.
+
+AcceptorThe: accepter thread is specifically responsible for establishing network connections(accept)。 After the new connection is created, instead of directly using the worker thread to process the request, the request is first sent to the poller buffer queue.
+Poller: in poller, a selector object is maintained. After poller takes the connection from the buffer queue, it registers in the selector and blocks to wait for read and write ready(Read wait ready, send wait ready)。
+Handlers: traverse the selector to find out the ready IO operations in the selector and hand them over to the worker thread for processing(Read memory read, decode, process, encode, send memory write)。
+
+  https://www.cnblogs.com/grey-wolf/p/13740845.html
+
+ 
+
+
+调优
+  https://tomcat.apache.org/tomcat-9.0-doc/config/http.html
+  https://www.datadoghq.com/blog/tomcat-architecture-and-performance/
+
+
+ 
+
+    

BIN
source/_posts/GC/企业微信截图_8b8b911d-8d45-4120-bad0-4aca1e62ccd1.png


+ 413 - 0
source/_posts/Google-Prompt-Engineering.md

@@ -0,0 +1,413 @@
+title: Google Prompt Engineering
+author: Gamehu
+tags:
+  - AI
+categories:
+  - 学习
+date: 2025-05-12 22:13:00
+---
+<div class="tag-container">
+  <span class="ai-tag">AI</span>
+  <span class="sub-tag">第五篇</span>
+</div>
+
+<div class="article-quote">
+
+这几天想起翻起来Google之前新发布的白皮书《Prompt Engineering》,学习下再简单用Claude提取下主要内容记录下。
+</div>
+
+
+# 掌握提示工程:打造AI高效交互的艺术与科学
+
+在人工智能迅猛发展的今天,提示工程(Prompt Engineering)已成为连接人类意图与AI输出的关键桥梁。Google最新发布的白皮书《Prompt Engineering》为我们提供了全面而深入的指南,让我们一起探索如何通过精心设计的提示让大语言模型发挥最大潜力。
+
+## 提示工程的本质
+
+提示工程是设计高质量提示的过程,旨在引导大语言模型(LLM)产生准确、相关且有用的输出。正如白皮书中所强调的:
+
+> "你不需要成为数据科学家或机器学习工程师——每个人都可以编写提示。然而,设计最有效的提示可能很复杂。"
+
+大语言模型本质上是一个预测引擎,它接收序列文本作为输入,然后基于训练数据预测下一个词元(token)应该是什么。当你编写提示时,你正在尝试设置LLM以预测正确的词元序列。
+
+## 理解大语言模型的输出配置
+
+在开始提示工程之前,了解如何配置LLM输出至关重要:
+
+### 输出长度控制
+
+控制模型生成的词元数量是一项重要配置。生成更多词元需要更多计算资源,导致能耗增加、响应时间潜在变慢,以及成本提高。限制输出长度对于某些提示技术特别重要,如ReAct(推理与行动),在这种情况下,LLM会在你想要的响应后继续生成无用词元。
+
+### 采样控制机制
+
+LLM不会正式预测单个词元,而是为每个可能的下一个词元分配概率。这些词元概率然后被采样以确定下一个生成的词元。
+
+#### 温度参数
+
+温度控制词元选择中的随机性程度:
+- **低温度**(接近0):适用于需要确定性响应的提示,选择概率最高的词元
+- **高温度**(接近1或更高):产生更多样化或意外的结果,使所有词元被选中的可能性更加均等
+
+#### Top-K和Top-P(核采样)
+
+这两种设置限制预测的下一个词元只能来自概率最高的词元:
+- **Top-K采样**:从模型预测分布中选择K个最可能的词元
+- **Top-P采样**:选择累积概率不超过特定值(P)的最可能词元
+
+综合配置时,一般起点建议:
+- 相对连贯且有创意的结果:温度0.2,top-P 0.95,top-K 30
+- 特别有创意的结果:温度0.9,top-P 0.99,top-K 40
+- 较少创意的结果:温度0.1,top-P 0.9,top-K 20
+- 只有一个正确答案的任务(如数学问题):温度0
+
+## 提示技术详解
+
+### 零样本提示(Zero-shot)
+
+最简单的提示类型,仅提供任务描述和一些文本让LLM开始。适用于模型已经理解的简单任务。
+
+**示例**:
+```
+将电影评论分类为积极、中性或消极。
+评论:"她"是一项揭示人工智能发展方向的研究,如果AI继续不受控制地发展,人类将走向何方。我希望有更多像这样的杰作。
+情感:
+```
+
+### 单样本和少样本提示(One-shot & Few-shot)
+
+通过在提示中提供一个或多个示例,帮助模型理解所需的输出格式或模式。这种方法特别适用于需要特定输出结构的任务。
+
+**示例**:
+```
+解析客户的披萨订单为有效的JSON:
+
+例子1:
+我想要一个小号披萨,配芝士、番茄酱和意大利香肠。
+JSON响应:
+{
+  "size": "small",
+  "type": "normal",
+  "ingredients": [["cheese", "tomato sauce", "pepperoni"]]
+}
+
+例子2:
+我想要一个大号披萨,配番茄酱、罗勒和马苏里拉奶酪。
+{
+  "size": "large",
+  "type": "normal",
+  "ingredients": [["tomato sauce", "basil", "mozzarella"]]
+}
+
+现在,我想要一个大号披萨,一半是芝士和马苏里拉奶酪,另一半是番茄酱、火腿和菠萝。
+JSON响应:
+```
+
+少样本提示的示例数量取决于任务复杂性、示例质量和模型能力。一般建议至少使用3-5个示例,复杂任务可能需要更多。
+
+### 系统、角色和上下文提示
+
+这三种技术都用于引导LLM生成文本,但侧重点不同:
+
+#### 系统提示
+
+设置语言模型的整体上下文和目的,定义模型应该做什么的"大局观"。
+
+**示例**:
+```
+将电影评论分类为积极、中性或消极。只返回大写的标签。
+评论:"她"是一部揭示AI不受控制进化可能导致人类走向何方的令人不安的研究。它太令人不安以至于我无法观看完。
+情感:
+```
+
+#### 角色提示
+
+为语言模型分配特定角色或身份,帮助模型生成与该角色一致的响应。
+
+**示例**:
+```
+我希望你扮演旅游指南的角色。我会告诉你我的位置,你将为我推荐3个附近可以参观的地方。在某些情况下,我还会告诉你我想参观的地点类型。
+我的建议:"我在阿姆斯特丹,我只想参观博物馆。"
+旅游建议:
+```
+
+#### 上下文提示
+
+提供与当前对话或任务相关的具体细节或背景信息,帮助模型理解要求的细微差别。
+
+**示例**:
+```
+上下文:你正在为一个关于80年代街机视频游戏的博客撰写文章。
+建议3个可以撰写文章的主题,并简要描述这些文章应该包含什么内容。
+```
+
+### 退一步提示(Step-back)
+
+先考虑与特定任务相关的一般问题,然后将答案用于后续提示,激活相关背景知识和推理过程。
+
+**示例**:
+```
+步骤1:基于流行的第一人称射击游戏,什么是5个虚构的关键设置有助于第一人称射击游戏中挑战和引人入胜的关卡故事线?
+
+步骤2:利用上面的主题,为第一人称射击游戏编写一个新关卡的一段故事情节,既具挑战性又引人入胜。
+```
+
+### 思维链提示(Chain of Thought)
+
+通过生成中间推理步骤来改善推理能力,特别适用于数学问题、逻辑推理等需要分步思考的任务。
+
+**示例**:
+```
+当我3岁时,我的伙伴是我年龄的3倍。现在,我20岁了。我的伙伴多大?让我们一步一步思考。
+
+1. 当我3岁时,我的伙伴是3*3=9岁。
+2. 这意味着我的伙伴比我大6岁。
+3. 现在我20岁了,所以我的伙伴应该是20+6=26岁。
+因此,我的伙伴现在26岁。
+```
+
+思维链提示可以与单样本或少样本结合使用,效果更佳:
+
+```
+问题:当我哥哥2岁时,我的年龄是他的两倍。现在我40岁了。我哥哥多大?让我们一步一步思考。
+答案:当我哥哥2岁时,我是2*2=4岁。这意味着我比他大2岁。现在我40岁了,所以我哥哥是40-2=38岁。答案是38。
+
+问题:当我3岁时,我的伙伴是我年龄的3倍。现在,我20岁了。我的伙伴多大?让我们一步一步思考。
+答案:
+```
+
+### 自我一致性(Self-consistency)
+
+结合抽样和多数投票,生成多样化的推理路径并选择最一致的答案。这种方法改进了LLM在各种任务中的准确性和回答一致性。
+
+**过程**:
+1. 使用相同提示多次,生成不同的推理路径
+2. 从每个生成的响应中提取答案
+3. 选择最常见的答案
+
+### 思维树(Tree of Thoughts)
+
+允许LLM同时探索多个不同的推理路径,通过在树的不同节点分支来解决问题。特别适合需要探索的复杂任务。
+
+### 推理与行动(ReAct)
+
+结合自然语言推理与执行外部工具操作的能力,使LLM能够解决复杂任务。例如,查询网络获取信息,然后基于结果继续推理。
+
+**Python示例**:
+```python
+from langchain.agents import load_tools
+from langchain.agents import initialize_agent
+from langchain.agents import AgentType
+from langchain.llms import VertexAI
+
+prompt = "Metallica乐队成员有多少个孩子?"
+llm = VertexAI(temperature=0.1)
+tools = load_tools(["serpapi"], llm=llm)
+agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
+agent.run(prompt)
+```
+
+### 自动提示工程(Automatic Prompt Engineering)
+
+利用LLM自身生成更多提示,评估它们,并可能修改好的提示,然后重复这个过程:
+
+1. 编写生成输出变体的提示
+2. 根据选定指标评估所有指令候选
+3. 选择评估分数最高的指令候选
+
+## 代码提示技巧
+
+### 编写代码提示
+
+LLM可以帮助开发人员加速编写代码过程,实现各种自动化任务:
+
+**示例**:
+```
+用Bash编写一个代码片段,询问文件夹名称。然后将该文件夹的内容重命名,在文件名前加上"draft"。
+```
+
+### 解释代码提示
+
+LLM也可以帮助理解他人的代码:
+
+**示例**:
+```
+解释以下Bash代码:
+#!/bin/bash
+echo "Enter the folder name: "
+read folder_name
+if [ ! -d "$folder_name" ]; then
+  echo "Folder does not exist."
+  exit 1
+fi
+files=( "$folder_name"/* )
+for file in "${files[@]}"; do
+  new_file_name="draft_$(basename "$file")"
+  mv "$file" "$new_file_name"
+done
+echo "Files renamed successfully."
+```
+
+### 翻译代码提示
+
+将代码从一种语言翻译到另一种语言:
+
+**示例**:
+```
+将以下Bash代码翻译为Python片段:
+[Bash代码]
+```
+
+### 调试和审查代码提示
+
+修复代码中的错误并提供改进建议:
+
+**示例**:
+```
+以下Python代码报错:
+Traceback (most recent call last):
+ File "/Users/leeboonstra/Documents/test_folder/rename_files.py", line 7, in <module>
+ text = toUpperCase(prefix)
+NameError: name 'toUpperCase' is not defined
+
+调试错误并解释如何改进代码。
+[Python代码]
+```
+
+## 提示工程最佳实践
+
+### 提供示例
+
+在提示中提供示例是最重要的最佳实践之一,它作为强大的教学工具,展示期望的输出或类似响应,提高模型输出的准确性、风格和语调。
+
+### 设计简单
+
+提示应简洁、清晰、易于理解。如果对你来说已经令人困惑,对模型来说也可能如此。避免使用复杂语言和提供不必要的信息。
+
+**示例改进**:
+```
+改进前:
+我现在正在纽约参观,想了解更多关于好地方的信息。我带着两个3岁的孩子。我们假期应该去哪里?
+
+改进后:
+作为旅游指南,描述纽约曼哈顿适合带3岁孩子参观的好地方。
+```
+
+### 明确输出要求
+
+具体说明所需的输出形式。简洁的指令可能无法充分引导LLM或过于笼统。
+
+**示例**:
+```
+生成一篇关于5大视频游戏主机的3段落博客文章。博客文章应该信息丰富且引人入胜,并以对话风格撰写。
+```
+
+### 使用指令而非约束
+
+指令和约束在提示中用于引导LLM输出,但研究表明,专注于积极指令比严重依赖约束更有效:
+
+- **指令**:直接传达期望的结果
+- **约束**:设置响应的限制或边界
+
+**示例**:
+```
+推荐做法:
+生成一段关于5大视频游戏主机的博客文章。只讨论主机、制造公司、发布年份和总销量。
+
+避免做法:
+生成一段关于5大视频游戏主机的博客文章。不要列出视频游戏名称。
+```
+
+### 控制最大令牌长度
+
+通过配置或在提示中明确要求特定长度来控制生成的LLM响应长度:
+
+```
+用推特长度的消息解释量子物理学。
+```
+
+### 在提示中使用变量
+
+使用变量使提示更加动态和可重用,特别是在集成到应用程序中时:
+
+```
+变量:
+{city} = "阿姆斯特丹"
+
+提示:
+你是一名旅游指南。告诉我关于这个城市的一个事实:{city}
+```
+
+### 实验输入格式和写作风格
+
+不同的模型、配置、提示格式、词汇选择可能产生不同结果。因此,尝试不同的提示属性如风格、词汇选择和提示类型(零样本、少样本、系统提示)非常重要。
+
+**例如**,关于Sega Dreamcast的提示可以表述为:
+- 问题:Sega Dreamcast是什么,为什么它是如此革命性的主机?
+- 陈述:Sega Dreamcast是世嘉在1999年发布的第六代视频游戏主机...
+- 指令:写一段描述Sega Dreamcast主机并解释为什么它如此革命性的段落。
+
+### 分类任务中混合类别
+
+对于分类任务的少样本提示,确保混合可能的响应类别,避免模型只是记住示例顺序而非学习每个类别的关键特征。
+
+### 适应模型更新
+
+随时了解模型架构变化、添加的数据和新功能。尝试新版模型并调整提示以更好地利用新特性。
+
+### 尝试不同输出格式
+
+考虑实验输出格式,对于非创意任务(如提取、选择、解析、排序、排名或分类数据),尝试使用JSON或XML等结构化格式。
+
+**JSON输出优势**:
+- 始终以相同风格返回
+- 专注于您想要接收的数据
+- 降低幻觉风险
+- 使其关系感知
+- 获得数据类型
+- 可以排序
+
+## 处理JSON输出的特殊考虑
+
+### JSON修复
+
+虽然以JSON格式返回数据提供了众多优势,但也存在一些缺点。JSON的结构化特性虽然有利于解析和在应用程序中使用,但需要比纯文本更多的词元,导致处理时间增加和成本提高。此外,JSON的冗长可能轻易消耗整个输出窗口,特别是当生成由于词元限制而突然中断时,这通常会导致缺少关键的闭合大括号或方括号,使输出无法使用。
+
+幸运的是,`json-repair`库(可在PyPI上获取)在这些情况下非常宝贵。此库智能地尝试自动修复不完整或格式错误的JSON对象。
+
+### 使用JSON模式
+
+JSON模式定义了JSON输入的预期结构和数据类型。通过提供模式,您为LLM提供了一个清晰的数据蓝图,帮助它专注于相关信息并减少误解输入的风险。此外,模式可以帮助建立不同数据片段之间的关系,甚至通过包含特定格式的日期或时间戳字段使LLM"时间感知"。
+
+## 与其他提示工程师合作实验
+
+如果您需要尝试制定良好的提示,找多人进行尝试可能会有所帮助。当每个人都遵循最佳实践时,您会看到不同提示尝试之间的性能差异。
+
+## 思维链最佳实践
+
+- 在推理之后放置答案是必需的,因为推理的生成会改变模型在预测最终答案时获得的词元
+- 使用思维链和自我一致性时,需要能够从提示中提取最终答案,与推理分开
+- 对于思维链提示,将温度设置为0
+- 思维链提示基于贪婪解码,根据语言模型分配的最高概率预测序列中的下一个词。通常,在使用推理得出最终答案时,可能只有一个正确答案,因此温度应始终设置为0
+
+## 记录提示尝试
+
+详细记录您的提示尝试至关重要,这样您可以随着时间的推移了解什么有效,什么无效。建议使用谷歌表格,包含以下字段:
+
+- 名称
+- 目标
+- 模型
+- 温度
+- 令牌限制
+- Top-K
+- Top-P
+- 提示
+- 输出
+
+除了这些字段外,跟踪提示版本(迭代)、结果是否OK/NOT OK/SOMETIMES OK的字段,以及反馈字段也很有帮助。
+
+## 结语
+
+提示工程是一门艺术,也是一门科学,需要持续的实践和改进。通过掌握本白皮书中详述的各种技术和最佳实践,您可以有效地引导大语言模型产生准确、相关且有用的输出,充分发挥AI的潜力,无论是用于个人项目还是企业级应用。
+
+记住,提示工程是一个迭代过程。设计并测试不同的提示,分析并记录结果。根据模型的表现优化您的提示。不断实验,直到达到所需的输出。当您更换模型或模型配置时,回顾并继续使用先前使用的提示进行实验。
+
+通过这种方法,您将能够与AI系统建立更有效、更精确的交互,释放其真正的潜力。

+ 75 - 0
source/_posts/GraphQL.md

@@ -0,0 +1,75 @@
+title: GraphQL
+author: Gamehu
+tags:
+  - graphql
+categories:
+  - 工作
+date: 2018-08-06 15:24:00
+---
+
+前后端关于CMDB的交互决定选用GraphQL,因为第一次听说就抓紧时间了解了以下是个什么东西。
+
+##  GraphQL干嘛的? ##
+
+{% blockquote Overview http://spec.graphql.cn/#sec-Overview- %}
+{% endblockquote %}
+
+*GraphQL语言致力于提供一种直观的弹性语法系统,用以描述客户端程序设计时的数据需求以及数据交互行为。*
+
+说的直白点就是能让API设计变得更加的灵活,你想要什么数据就给你什么数据,不多不少。
+
+## 实践 ##
+
+目前只有CMDB那一块使用的GraphQL,其它的前后端交互还是用的传统的方式。
+
+不过这并不影响我对它的兴趣,新东西总是喜欢琢磨琢磨,更何况GraphQL有大厂的背书,那证明它的潜力是巨大地。
+
+- 传统的api设计,如果想要多种场景公用一个接口,比如都是获取用户信息,A场景需要name,B场景需要name+sex,C场景需要name+introduction,很显然都是获取用户信息,但是每个场景要求的数据不一样,如果简单粗暴的直接返回整个用户信息,很显然不太科学,极端一点假设用户有20个字段,调用方只需要一个字段,你给20个字段完全是浪费,另一种方案是写三个接口,但是三个接口很显然太冗余了,所以通常是公用一个接口,但是共有一个接口就肯定免不了一堆逻辑判断,此外,这样还会造成不同业务之间的耦合,每次发布都需要各个业务场景一起测试和回归。
+
+**这种时候痛点就出现了,不重用接口则没法提高开发效率,重用接口则会有这些问题。**
+
+这个时候GraphQL就体现它的优势了,我认为它的出现就是为了解决上面的痛点。出现上面的问题的根本原因我认为在于,前端不能直白的告诉后端我要什么数据,必须通过后端经过对应的翻译转换,因为前端没有合适的方式来告诉我们A只需要name,B只需要name+sex,它可能就给我们一个userId然后给个businessCase然后我们根据businessCase来进行逻辑判断,进行数据查询,进行数据筛选以及过滤。
+
+
+
+## GraphQL ##
+
+花点时间写这个,是因为觉得GraphQL算是开阔了我的技术视野,我们其实还用的很浅,他的**一切皆是图**、**API无版本(某些场景)**的思想,以及schema、别名、片段、指令、mutation、元字段等概念让GraphQL灵活的像猴哥,至少目前我们没有遇到有什么场景是满足不了的,至少对于技术浅薄的我来说是有开到脑洞。
+
+
+
+
+
+[我为什么要放弃RESTful,选择拥抱GraphQL](https://mp.weixin.qq.com/s?__biz=MzI4Njc5NjM1NQ==&mid=2247501981&idx=1&sn=4cefea59913ac291f7fafcf4a3a007a0&chksm=ebd5f7b1dca27ea779ea35b8521d91b85239d9b5d64489e394be76347c72a0968ce616b1597d&mpshare=1&scene=1&srcid=0108kwmT37WixQYNhMCOnZQ4&sharer_sharetime=1610066466233&sharer_shareid=77df2eafd0a472623696abf038541666&version=3.1.1.3001&platform=win#rd)
+
+[graphql工具社区](https://github.com/chentsulin/awesome-graphql)
+
+学习地址:
+
+{% blockquote learn http://graphql.cn/learn/ %}
+{% endblockquote %}
+
+{% blockquote learn https://www.howtographql.com %}
+{% endblockquote %}
+
+{% blockquote  graphql-up https://github.com/prisma/graphql-up %}
+{% endblockquote %}
+
+
+
+这是我用nodejs实现的很简单的demo:
+
+{% blockquote demo https://github.com/WebHu/graph_demo.git %}
+{% endblockquote %}
+
+这是通过howtographql搭建的demo
+
+{% blockquote demo https://github.com/WebHu/graph_apollo_demo.git %}
+{% endblockquote %}
+
+
+
+https://flaviocopes.com/graphql-vs-rest/
+
+`本文引用的内容,如有侵权请联系我删除,给您带来的不便我很抱歉。`
+

+ 268 - 0
source/_posts/Gulp.md

@@ -0,0 +1,268 @@
+title: Gulp
+author: Gamehu
+tags:
+
+  - gulp
+categories:
+  - 前端
+date: 2020-02-28 21:11:00
+
+---
+
+是这样的,最近呢在捣鼓一系列升级的问题,刚好就遇到了Gulp从3升到4的过程,所以借机呢稍微深入的了解了一下Gulp,在此做个简单的记录。
+
+Gulp我一开始理解的他就是个样式处理工具,但实际了解下来,才发现它原来跟Grunt一样是个构建工具。
+
+那就开整吧,我按我的节奏来哈:
+
+1. **了解一些底层**,知道是怎么来的。
+2. **了解基本概念**,不但要知道是怎么来的,还要知道是干啥的。
+3. **了解语法** ,3->4升级实操
+
+
+
+### 一些底层
+
+Gulp 是基于 [Node.js](http://nodejs.org/) 的项目,它的核心使用的是Node.js四种流中的[Transform](http://nodejs.cn/s/fhVJQM) - `在读写过程中可以修改或转换数据的 Duplex流` 。即可读又可写的流,它会对传给它的对象做一些转换的操作。
+
+
+
+因为基于Streams,而Streams和其它数据处理方法相比最大的优点:
+
+1. 内存效率:我们无需先将大量数据加载到内存中即可进行处理。它就像往河里(Pipe)倒水一样,一桶水你可以分很多次倒。
+2. 时间效率:拥有数据后立即开始处理数据所需的时间大大减少,而不必等到整个有效负载都传输完成才开始处理。还是倒水的例子,你倒入河里(Pipe)马上就流走了不会等着一桶水倒完之后才流走。
+
+
+
+Streams的*cheatsheet*:
+
+{% asset_img   stream_cc.png from https://devhints.io/nodejs-stream %}
+
+
+
+Duplex:
+
+{% asset_img   duplex.png from [Duplex](http://codewinds.com/blog/2013-08-31-nodejs-duplex-streams.html) %}
+
+
+
+Streams内部实现流程图:
+
+{% asset_img   stream01.png from [DauleDK](https://stackoverflow.com/users/3694288/dauledk) %}
+
+
+
+想了解细节的推荐去看[stream-handbook](https://github.com/substack/stream-handbook)、[Video introduction to node.js streams](http://www.youtube.com/watch?v=QgEuZ52OZtU)。通过学习之后我真的认为Node的Streams是正儿八经牛X的存在,对我来说简直是一颗遗珠啊。
+
+
+
+### 基本概念
+
+**Task**
+
+每个 gulp 任务(task)都是一个异步的 JavaScript 函数,此函数是一个可以接收 callback 作为参数的函数,或者是一个返回 stream、promise、event emitter、child process 或 observable ([后面会详细讲解](https://www.gulpjs.com.cn/docs/getting-started/async-completion)) 类型值的函数。 
+
+任务(tasks)可以是 **public(公开)** 或 **private(私有)** 类型的。
+
+- **公开任务(Public tasks)** 从 gulpfile 中被导出(export),可以通过 `gulp` 命令直接调用。
+- **私有任务(Private tasks)** 被设计为在内部使用,通常作为 `series()` 或 `parallel()` 组合的组成部分。
+
+**Gulpfile**
+
+Gulp 允许你使用现有 JavaScript 知识来书写 gulpfile 文,gulpfile 是项目目录下名为 `gulpfile.js` (或者首字母大写 `Gulpfile.js`,就像 Makefile 一样命名)的文件,在运行 `gulp` 命令时会被自动加载。在这个文件中,你经常会看到类似 `src()`、`dest()`、`series()` 或 `parallel()` 函数之类的 gulp API,除此之外,纯 JavaScript 代码或 Node 模块也会被使用。任何导出(export)的函数都将注册到 gulp 的任务(task)系统中。
+
+**处理文件**
+
+gulp 暴露了 `src()` 和 `dest()` 方法用于处理计算机上存放的文件。
+
+`src()` 接受 [glob](https://www.gulpjs.com.cn/docs/getting-started/explaining-globs) 参数,并从文件系统中读取文件然后生成一个 [Node 流(stream)](https://nodejs.org/api/stream.html)。它将所有匹配的文件读取到内存中并通过流(stream)进行处理。
+
+流(stream)所提供的主要的 API 是 `.pipe()` 方法,用于连接转换流(Transform streams)或可写流(Writable streams)。
+
+`dest()` 接受一个输出目录作为参数,并且它还会产生一个 [Node 流(stream)](https://nodejs.org/api/stream.html),通常作为终止流(terminator stream)。当它接收到通过管道(pipeline)传输的文件时,它会将文件内容及文件属性写入到指定的目录中。gulp 还提供了 `symlink()` 方法,其操作方式类似 `dest()`,但是创建的是链接而不是文件( 详情请参阅 [`symlink()`](https://www.gulpjs.com.cn/docs/api/symlink) )。
+
+大多数情况下,利用 `.pipe()` 方法将插件放置在 `src()` 和 `dest()` 之间,并转换流(stream)中的文件。
+
+**Glob**
+
+glob 是由普通字符和/或通配字符组成的字符串,用于匹配文件路径。可以利用一个或多个 glob 在文件系统中定位文件。
+
+> *(一个星号):在一个字符串片段中匹配任意数量的字符,包括零个匹配。对于匹配单级目录下的文件很有用。
+>
+> ** (两个星号):在多个字符串片段中匹配任意数量的字符,包括零个匹配。 对于匹配嵌套目录下的文件很有用。请确保适当地限制带有两个星号的 glob 的使用,以避免匹配大量不必要的目录。
+>
+>  ! (取反):由于 glob 匹配时是按照每个 glob 在数组中的位置依次进行匹配操作的,所以 glob 数组中的取反(negative)glob 必须跟在一个非取反(non-negative)的 glob 后面。第一个 glob 匹配到一组匹配项,然后后面的取反 glob 删除这些匹配项中的一部分。如果取反 glob 只是由普通字符组成的字符串,则执行效率是最高的。
+
+**插件**
+
+Gulp 插件实质上是 [Node 转换流(Transform Streams)](https://github.com/rvagg/through2),它封装了通过管道(pipeline)转换文件的常见功能,通常是使用 `.pipe()` 方法并放在 `src()` 和 `dest()` 之间。他们可以更改经过流(stream)的每个文件的文件名、元数据或文件内容。
+
+
+
+**Gulp**
+
+{% asset_img   Gulp.png from 我 %}
+
+
+
+Gulp的*cheatsheet*:
+
+{% asset_img   gulp01.png from https://github.com/osscafe/gulp-cheatsheet %}
+
+
+
+{% asset_img   gulp02.png from https://github.com/osscafe/gulp-cheatsheet %}
+
+
+
+### Gulp 3 - > 4 实操
+
+3其实算是废弃了,当然还是可以用的,只是不维护了。所以升一升还是极好的。
+
+1. 现卸载现有的
+
+```
+npm uninstall gulp --save-dev
+npm uninstall gulp -g
+```
+
+你以为升级完之后是这样色儿的
+
+{% asset_img   a.gif %}
+
+但是一执行是这样的:
+
+```
+AssertionError [ERR_ASSERTION]: Task function must be specified
+```
+
+{% asset_img   b.jpeg %}
+
+这是因为Gulp4只支持 2 个参数的 `gulp.task`了,所以就意味着咱们以前的代码得改了,那咱们就有疑问了怎么改呢?先了解下改了什么。
+
+#### **series、parallel**
+
+官网说了:Gulp.js 4.0引入了series()和parallel()方法来组合任务: 
+
+- series(...)按指定的顺序一次运行一个任务,并返回一个按给定的任务 / 函数的顺序执行的函数。
+
+- parallel(...)以任何顺序同时运行任务,并返回一个能并行执行给定的任务/函数的函数
+
+  
+
+  可见Gulp做出了很大的努力来实现对任务运行方式的更多控制,提供了选择顺序或并行执行任务的能力,避免之前需要添加别的依赖(传统上是使用 [run-sequence](https://www.npmjs.com/package/run-sequence))或者丧心病狂地手动分配任务执行的依赖。。
+
+所以,如果之前你有这样一个任务:
+
+```
+gulp.task('copy_css', ['clean_temp'], function() {
+    ...
+});
+```
+
+它将会变为:
+
+```
+gulp.task('copy_css', gulp.series('clean_temp', function() {
+    ...
+}));
+```
+
+当做出这个改变时,不要忘了你的任务函数现在在 `gulp.series` 的回调函数里。所以你需要在尾部多出来的那个括号。这很容易被忽略。
+
+注意到 `gulp.sereis` 与 `gulp.parallel` 会返回函数,所以它们可以被嵌套。当你的任务有多个依赖时,你可能需要经常地嵌套它们。
+
+例如,这个常见的模式:
+
+```
+gulp.task('default', ['copy_css', 'copy_image'], function() {
+    ...
+});
+```
+
+将会变为:
+
+```
+gulp.task('default', gulp.series(gulp.parallel('copy_css', 'copy_image'), function() {
+    ...
+}));
+```
+
+#### 依赖问题
+
+这是一个坑点,在 Gulp 3 中,如果你为多个任务指定了同一个依赖,并且它们都在运行时,Gulp 会意识到它们都依赖相同的任务,然后只执行一次这个被依赖的任务。而在 Gulp 4 中,我们不再指定"依赖",而是使用 `series` 或 `parallel` 来组合函数,这导致 Gulp 不能判断哪些任务在当它只应运行一次时会被多次运行。所以我们需要改变我们对依赖的处理方式。我们需要把依赖从任务中抽离出来,并在一个更大的“父级”任务中把依赖指明成一个 `series`。
+
+```
+// 这些任务不再有任何依赖
+gulp.task('copy_css', function() {...});
+gulp.task('copy_image', function() {...});
+gulp.task('clean_temp', function() {...});
+
+// default 依赖于 copy_css 与 copy_image
+gulp.task('default', gulp.series('clean_temp', gulp.parallel('copy_css', 'copy_image')));
+```
+
+
+
+#### 使用普通函数
+
+因为现在每一个任务实际上都只是一个函数,也并没有依赖或者其他特别的东西。所以我们不必每个任务都用 `gulp.task` 来完成。开始拥抱独立的函数而不用再像之前通过传入 `gulp.task` 的回调函数来写代码:
+
+```
+gulp.task('copyGlobalImage', function() {...});
+gulp.task('copyCss', function() {...});
+gulp.task('copyGlobalFont', function() {...});
+gulp.task('copyAllImage', function() {...});
+
+gulp.task('copy', series(['copy-static'], gulp.parallel('copyGlobalImage', 'copyCss','copyGlobalFont','copyAllImage')));
+```
+
+```
+//改成以下这样
+function themeResourcesCopy(srcPath, destPath, infoMsg) {
+  let res = null;
+  for (let i = 0; i < theme.length; i += 1) {
+    for (let j = 0; j < color.length; j += 1) {
+      res = gulp
+        .src(srcPath)
+        .pipe(info(infoMsg))
+        .pipe(gulp.dest(`${buildTargetPath + color[j]}/${theme[i]}${destPath}`));
+    }
+  }
+  return res;
+}
+
+function copyGlobalImage() {
+  // 目前不考虑同步情况
+  const g_image = '_global/image/';
+  info(`${targetTemp + g_image}**`);
+  return themeResourcesCopy(`${targetTemp + g_image}**`, '/image/', DIS.image_copy_g);
+}
+...
+
+// 记得去掉引号
+gulp.task('copy', series(['copy-static'], parallel(copyGlobalImage, copyCss, copyGlobalFont, copyAllImage)));
+```
+
+
+
+### 最后
+
+第一次接触所以就这样吧,后续会对这块进行优化,因为我发现之前的同事这块写的太复杂了且没有用一些压缩之类的插件,也是一开始都是大家都是开荒,可能都不是专业的,反正团队里比较open,只要不影响原有的功能,优化没人管。
+
+
+
+
+
+#### 感谢
+
+{% blockquote 少年阿布DX https://www.zcfy.cc/article/the-complete-ish-guide-to-upgrading-to-gulp-4  升级至 Gulp 4 的近完整指南 %}
+
+{% endblockquote %}
+
+
+
+{% blockquote 少年阿布DX https://www.zcfy.cc/article/the-complete-ish-guide-to-upgrading-to-gulp-4  升级至 Gulp 4 的近完整指南 %}
+
+{% endblockquote %}
+

BIN
source/_posts/Gulp/Gulp.png


BIN
source/_posts/Gulp/a.gif


BIN
source/_posts/Gulp/b.jpeg


BIN
source/_posts/Gulp/duplex.png


BIN
source/_posts/Gulp/gulp01.png


BIN
source/_posts/Gulp/gulp02.png


BIN
source/_posts/Gulp/stream.png


برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است