今日离京

昨天我开车去了南边的市场,一路经过那些熟悉又陌生的道路,曾经无数次往返的高架桥、路口和辅路,依旧保持着记忆中的样子。处理完事情后,我经过四号线生物医药基地站,这个地方我们当年也来看过房子。那时候孩子还没出生,对未来有着各种具体而清晰的规划,我们站在售楼处的沙盘前,认真计算着首付、月供和通勤时间,仿佛只要把这些数字安排妥当,未来就会按照预想的轨迹展开。 这么多年过去,再次站在那里,除了新建起来的楼盘、旧了一些的居民楼和商厦,似乎并没有太大的变化。地铁口依旧是匆匆赶路的人。街边的小店依旧亮着灯,大概率晚高峰的人潮依旧拥挤。人还是那些人,城市还是那座城市,变化最大的,反而是自己。 无论如何,该处理的事情都已经处理清楚,那些压在心头许久的事务,在签字、确认、交接之后,终于落下帷幕。走出最后一道门的时候,没有想象中的如释重负,反而有一种说不出的恍惚。就像一本翻了很多年的书,忽然合上,手还停留在最后一页。 对于北京,我有感激,也有遗憾;有留恋,也有释然。它见证了我最重要的十六年,而我把十六年的青春时光,都留在了这里。从一个背着行李、怀揣着各种幻想的年轻人,到如今两鬓渐添风霜,身边有了爱人,有了孩子,也有了属于自己的故事。回头看,这十六年几乎走完了一个普通人在大城市里最完整的人生轨迹。 恋爱、买房、结婚、生子。每一个阶段都曾经觉得漫长,等真正走过之后,却发现不过是转眼之间。我把所得一切主要归功于运气,北京没有亏待过我,它给过机会,也给过回报;给过希望,也给过挫折。那些为了生活奔波的清晨,那些加班到深夜的灯光,那些堵在路上的焦躁,那些拿到结果时的欣喜,都已经成为生命的一部分。 当然,我对这座城市也有很多不满。它拥挤、昂贵、节奏飞快;有时候让人觉得渺小得像一粒尘埃。很多时候,你拼尽全力,也未必能够追上它前进的速度,年轻时总觉得自己能够改变什么,后来才明白,个人终究改变不了一座城市。 幸运的是,人可以改变自己,接受自己的局限,接受时代的变化,也接受人生不同阶段的选择。 今天早晨吃完早餐,我们坐高铁出发。车站里行李箱轮子在地面滚动,西站依然熙熙攘攘,有人刚刚抵达,有人准备离开。人生很多时候也是如此,有人进入一段故事,有人结束一段故事。 车子驶出西站的时候,我没有刻意回头,因为真正重要的东西,其实早已带在身上。那些一起奋斗过的岁月,那些结识过的人,那些深夜里的梦想和迷茫,那些属于青春的热烈与倔强,都不会因为离开而消失,它们已经成为生命的一部分。 列车即将驶向远方,窗外的风景会不断后退,新的风景也会不断出现。人生终究是一场向前的旅程。 告别不是结束,而是另一段故事的序章。带着对过往的感激,带着对未来的期待,我们终于出发。

January 18, 2025

行走在北京胡同:历史没有如果,但仍有温度可守

入秋以来,我给自己安排了一场漫长的城市漫游。十多天时间里,几乎每天步行两万步以上,穿行于北京二环内纵横交错的胡同巷陌之间。从寻常百姓的小门小院,到昔日王公贵族的深宅大院;从熙熙攘攘的街市,到香火隐约的古寺庙宇;从规整修缮后的历史街区,到那些地图上甚至没有名字的狭窄角落。我像一个迟来的访客,试图在城市飞速变化的今天,重新认识这座古老都城的肌理。 有时,我也会壮着胆子走进那些看起来有些凌乱的院落。斑驳的墙面、堆放的杂物、晾晒的衣服、停靠的自行车,以及院子深处偶尔传来的锅碗碰撞声和家长里短的交谈声,共同构成一种真实而具体的生活景象。这些地方或许并不美观,甚至显得拥挤杂乱,但正是在这样的空间里,我感受到一种难以复制的城市温度。 每一次走进胡同,仿佛都是一次时空切换。仅仅隔着一条主干道,外面的世界是车流、人潮、商场和写字楼,是不断更新的广告牌和闪烁的霓虹灯。而拐进胡同之后,仿佛进入了另一个维度。除了偶尔匆忙穿行的外卖电动车,更多时候能够听见的只是自行车轮压过地面的细微声响,以及行人不紧不慢的脚步声。 这里没有现代都市常见的压迫感。低矮的屋檐、曲折的巷道、树木投下的阴影,以及那些历经岁月洗礼的砖墙,共同营造出一种缓慢而安静的节奏。行走其中,人会不自觉地放慢脚步,开始留意门楣上的砖雕、墙角的石墩、残存的匾额,甚至是一棵从院墙里探出枝叶的老树。 每当这种时候,我总会产生许多关于历史的假设。如果北京的老城墙能够完整保留下来,会是怎样的景象?如果那些规模宏大的城门、角楼和护城河至今依旧环绕着老城,北京是否会拥有另一种独特的气质?如果大量四合院没有被改造成大杂院,也没有在城市建设浪潮中被拆除,那么今天的人们是否还能更完整地感受到传统居住文化的魅力?如果那些散布于街巷之间的古老庙宇、牌楼和历史街道没有遭到破坏,北京又会呈现出怎样丰富而完整的历史层次? 然而,历史终究没有如果。 城市的发展从来不是静止的。北京能够成长为今天这样一座现代化国际都市,离不开过去几十年的快速建设与扩张。宽阔的道路、高耸的楼宇、发达的交通网络以及繁荣的商业中心,共同支撑着数千万人的工作与生活。 我当然喜欢西单和王府井的热闹繁华,也深知国贸、金融街和中关村对于这座城市的重要意义。那里汇聚着资本、技术、人才与机会,是现代北京最具活力的象征。 我甚至向往东四环那些环境优越的高端社区,以及京郊掩映在树林与湖泊之间的低调别墅。现代化带来的便利、舒适和效率,没有人能够轻易否认它们的价值。 但与此同时,我仍然认为,由短视和人为因素造成的文化断层,是这座城市无法回避的遗憾。这种遗憾并不仅仅体现在某一座建筑的消失,或者某一条街道的改变,而是在于一个完整文化生态的断裂。城市真正珍贵的东西,往往不仅是那些被列入保护名录的古建筑本身,更是建筑背后的生活方式、邻里关系、空间结构以及代代相传的记忆。当这些东西被整体切断之后,即便未来投入再多资源进行复原,也很难重新获得原有的生命力。 因为建筑可以重建,生活却无法复制。这些年,关于胡同的存留与改造,始终存在着各种不同观点和争论。有人认为胡同代表落后的居住条件,应该让位于更高效、更现代的城市空间;也有人认为胡同是北京最独特的文化遗产,必须最大限度地保护。作为一个普通的行走者,我并非城市规划专家,也无法给出复杂问题的标准答案。只是经过这些天的观察与思考,我越来越觉得,与其进行大刀阔斧的彻底改造,不如给予这些空间更多自然生长的可能。因为我有一个非常深刻的体会:胡同里那些杂院和小杂货铺所散发出的市井气息,往往比大门紧闭的单位院落和空无一人的豪华大院更具生命力。 清晨开门扫地的老人,坐在门口择菜聊天的邻居,经营了几十年的小卖部,修车铺门前停放的自行车,放学后奔跑追逐的孩子,甚至是一只趴在墙根晒太阳的猫——这些看似微不足道的日常场景,恰恰构成了一座城市最真实的灵魂。城市的价值,不仅在于它拥有多少摩天大楼,也在于它是否还保留着普通人的生活痕迹。 那些杂乱、拥挤、甚至略显陈旧的空间,未必符合现代审美,却承载着人与人之间最自然的联系。它们不是博物馆里的标本,而是仍然在呼吸、在生长、在变化的生活现场。当越来越多城市变得相似,当商业综合体和标准化街区不断复制扩张的时候,北京胡同最珍贵的地方,或许正是这种无法被复制的烟火气。 历史没有如果,失去的许多东西也无法重来。但至少今天,当我们仍然能够走进这些胡同,听见自行车铃声,看见院墙上的爬山虎,闻到早点铺升起的热气时,就意味着这座城市与自己的过去还没有完全失去联系。或许,对于北京而言,最重要的不是把胡同变成一件被精心陈列的展品,也不是将其彻底改造成整齐划一的新社区,而是在保护与更新之间找到一种克制而审慎的平衡。 让历史继续存在,让生活继续发生。 因为一座城市最动人的部分,从来不只是它的过去,而是过去仍然活在今天。

October 23, 2024

小提琴演奏主要基本功

小提琴的演奏技术来说,要练好以下几个主要基本功: 一、运弓 优秀的演奏家能在小提琴上发出千变万化的声音,就运弓而言,取决于运弓的速度、弓在弦上的压力以及弓和弦的接触点这3种因素的不同结合。小提琴的弓法繁多,就其主要的有以下几种: ①分弓:一弓演奏一个音; ②连弓:一弓演奏许多音; ③顿弓:音与音之间断开; ④跳弓:弓毛离开琴弦。 这4类弓法是最基本的,在20世纪中期,连顿弓,即在一弓中连续快速演奏许多音与音之间是断开的音,被人视为绝技,所以人们把小提琴演奏艺术称之为“运弓的艺术”。 二、揉弦 通过左手手指在弦上的颤动,使声音的音高产生有规律的波动,称之为揉弦。 揉弦是小提琴演奏中极为重要的表现手段。揉弦分为手指的、手腕的和手臂的。优秀的演奏者不仅要掌握这3种揉弦方法,而且要学会使用不同速度和不同幅度的揉弦,在演奏不同作家,不同作品,不同乐句时,富于变化地运用揉弦。从揉弦的运用,可以使听众明显地辨认出不同演奏家的音乐个性。 三、把位 左手手指在指板上的位置,称之为把位。靠近琴头的把位为低把,靠近琴马的为高把。从一个把位换到另一个把位,称为换把。 换把位的方法有多种,例如空弦换把,同指换把,不同指以及泛音换把等。换把时产生非音乐需要的滑音,是技巧训练不足的标志。滑音可以使音与音之间的连接富于变化,特别是结合换把使用滑音,是一种富于表现力的演奏手段。 四、双音与和弦 小提琴可以同时演奏两个音甚至是3个音,也可以分奏4个音的和弦,这不仅丰富了它的表现力,并可不依赖其他乐器的伴奏进行单独演奏。小提琴的三度、六度、八度以及十度双音音阶,是演奏双音的基础,也是小提琴家必须终身练习的一项基本功。小提琴演奏中的左手颤音、泛音、拨弦等,都是一些高深的技巧。

September 28, 2024

React官网力荐Next.js

随着前端技术的快速发展,React作为一款领先的JavaScript库,不断推动着前端开发的变革。近期,React官网的一个显著变化引起了广大开发者的关注:它不再推荐使用Create-React-App作为构建React应用的默认工具,而是转向了Next.js。 那么,Next.js究竟有何魔力,让React官网做出如此决策?本文将为你详细解析。 一、Next.js:React应用的“升级版” Next.js并不是一个全新的框架,而是基于React的服务器端渲染框架。它提供了许多开箱即用的功能,使得开发者能够更高效地构建复杂、高性能的React应用。与Create-React-App相比,Next.js更像是一个“升级版”,它为React应用带来了以下显著的优势: 性能优化:Next.js支持自动静态优化(Automatic Static Optimization)和服务器端渲染(Server-Side Rendering),使得页面加载速度更快,用户体验更流畅。此外,Next.js还支持预渲染(Pre-rendering)和动态导入(Dynamic Imports),进一步提升了应用的性能。 数据获取简化:Next.js内置了数据获取功能,使得开发者能够更方便地从API或其他数据源获取数据,并将其注入到组件中。这种无缝的数据获取流程大大简化了开发过程,提高了开发效率。 强大的路由功能:Next.js提供了基于文件系统的路由功能,使得页面之间的导航变得简单直观。开发者只需创建相应的页面文件,Next.js就能自动为其生成路由。这种方式不仅易于理解,还能减少错误和提高可维护性。 更好的SEO支持:由于Next.js支持服务器端渲染和预渲染,因此它能够更好地处理页面渲染和加载问题,从而提高网站的搜索引擎优化(SEO)效果。 二、Create-React-App的局限性 虽然Create-React-App为React开发者提供了一个快速搭建项目的脚手架,但随着项目规模的扩大和复杂度的增加,其局限性也逐渐显现: 配置不灵活:Create-React-App为开发者提供了一套固定的配置,虽然这降低了入门门槛,但对于有特定需求的开发者来说,这种固定配置可能会成为束缚。 性能优化有限:Create-React-App主要关注于项目的快速搭建和开发体验,对于性能优化方面的支持相对有限。对于需要高性能的应用来说,开发者可能需要花费更多的时间和精力进行手动优化。 扩展性不足:随着项目的发展,开发者可能需要集成更多的功能和工具。然而,Create-React-App的扩展性相对有限,可能无法满足一些高级需求。 三、React官网推荐的背后 React官网之所以推荐Next.js而非Create-React-App,背后有多重原因。 首先,Next.js作为React的“升级版”,在性能、数据获取、路由等方面提供了更强大的支持,能够更好地满足现代Web应用的需求。 其次,随着前端技术的不断发展,开发者对于高性能、易扩展的应用框架的需求也在不断增加。Next.js正好符合这一趋势,能够为开发者提供更高效、更灵活的开发体验。 最后,React官网的推荐也反映了社区对于Next.js的广泛认可和支持。越来越多的企业和项目采用Next.js构建应用,证明了其在实际应用中的价值和优势。 四、结语 React官网推荐使用Next.js而非Create-React-App,是基于对现代Web应用需求的深入理解和对前端技术发展趋势的敏锐洞察。对于广大React开发者来说,了解和掌握Next.js将是一个值得投入时间和精力的选择。它将帮助你更高效地构建高性能、易扩展的React应用,提升你的开发能力和竞争力。

September 9, 2024

React团队回应用Vite替换Create React App的建议

Create React App 的演变 在 2016 年发布 Create React App 时,工具的环境是分散的。如果想要将 React 添加到现有应用,需要添加一个 script 标签或从 npm 中导入,然后调整现有的构建工具配置。但是,如果要从头开始创建一个仅使用 React 构建的新应用,则没有明确的方法可以做到这一点。 在 Create React App 之前,必须安装一堆工具并将它们连接在一起,提供正确的预设以使用 JSX,为开发和生产环境进行不同的配置,为资源缓存提供正确的设置,配置 linter 等,想要正确完成这一系列工作非常困难。人们通过创建和共享可以克隆的“样板”存储库来解决了这个问题。然而,这产生了另外一个问题:一旦在项目中调整了克隆的样板文件,就很难再拉取样板的更新。这样,项目的设置会变得旧,要么放弃更新,要么花费大量精力让所有工具再次协同工作。在快速发展的生态系统中,这非常困难。 Create React App 通过将多个工具组合在一个包中解决了这个问题。现在,如果想用 React 开始一个新项目,有一个明确的推荐方法(Create React App)可以做到这一点! 然后,每隔一段时间,可以更新这个包,以获得所有底层工具的更新。这种模型变得很流行,以至于今天有很多工具都以这种方式工作。Vite 确实是拥有相似愿景的最佳工具之一,并且在在某些方面更进一步。 Create React App 的目标是为大多数 React 用户提供启动新 React Web 应用的最佳方式,它支持一组协同工作的精选功能。随着时间的推移,它提供的开箱即用的“baseline”会随着我们找到正确的权衡而扩大。 例如,为运行时错误添加了一个遮罩层,添加了对不同样式选项的支持,默认添加了快速刷新,它允许保存组件的代码并查看更改而不会丢失状态。对于默认的 React 开发体验来说,这是一个巨大的里程碑。总的来说,由于 Create React App 完全控制了编译管道,因此添加编译相关的功能是很容易的。 有这样一个精心策划的设置对生态系统仍然很有价值。当 React Hooks 出现时,React 团队将 React Hooks lint 规则添加到默认设置中。除此之外,Create React App 还允许 React 团队向尽可能广泛的受众部署重要的工具更改(快速刷新支持、React Hooks lint 规则)。 如果没有 React 团队策划的流行模板,将很难如此广泛地推出这些工具更改。 ...

July 25, 2024

Create React App和webpack

创建方法 npx: npx 来自 npm 5.2+ 或更高版本 npx create-react-app my-app npm: npm init 在 npm 6+ 中可用 npm init react-app my-app Yarn: yarn create 在 Yarn 0.25+ 中可用 yarn create react-app my-app Scripts 在新创建的项目中,你可以运行一些内置命令: npm start 或 yarn start 在开发模式下运行应用程序, 默认在浏览器打开http://localhost:3000。如果更改代码,页面将自动重新加载。 npm test 或 yarn test 以交互模式运行测试程序。 默认情况下,运行与上次提交后更改的文件相关的测试。 npm run build 或 yarn build 将生产环境的应用程序构建到 build 目录。 它能将 React 正确地打包为生产模式中并优化构建以获得最佳性能。构建将被压缩,文件名中将包含哈希。 npm run eject 注意:这是单向操作。一旦 eject ,就回不去了! 执行完这个命令后会将封装在 CRA 中的配置全部反编译到当前项目,这样开发者完全取得 webpack 文件的控制权,可以自定义修改webpack打包配置。 ...

July 9, 2024

MiniProfiler工具介绍

在日常开发中,应用程序的性能是我们需要关注的一个重点问题。当然我们有很多工具来分析程序性能:如:Zipkin等;但这些过于复杂,需要单独搭建。 MiniProfiler就是一款简单,但功能强大的应用新能分析工具;可以帮助我们定位:SQL性能问题、响应慢等问题。 MiniProfiler是一款针对.NET, Ruby, Go and Node.js的性能分析的轻量级程序。可以对一个页面本身,及该页面通过直接引用、Ajax、Iframe形式访问的其它页面进行监控,监控内容包括数据库内容,并可以显示数据库访问的SQL(支持EF、EF CodeFirst等 )。并且以很友好的方式展现在页面上。 MiniProfiler官网:http://miniprofiler.com/ MiniProfiler的一个特别有用的功能是它与数据库框架的集成。除了.NET原生的 DbConnection类,MiniProfiler还内置了对实体框架(Entity Framework)以及LINQ to SQL、RavenDb和MongoDB的支持。任何执行的Step都会包括当时查询的次数和所花费的时间。为了检测常见的错误,如N+1反模式,profiler将检测仅有参数值存在差异的多个查询。

June 26, 2024

数据访问策略: Dapper和Entity Framework混合应用

作者 Julie Lerman 你大概注意到了,自 2008 年以来,我写过许多关于 Entity Framework(即 Microsoft 对象关系映射器 (ORM))的文章,ORM 一直是主要的 .NET 数据访问 API。市面上还有许多其他 .NET ORM,但是有一个特殊类别因其强大的性能得到的关注最高,那就是微型 ORM。我听人提到最多的微型 ORM 是 Dapper。据不同的开发者说,他们使用 EF 和 Dapper 制定了混合解决方案,让每个 ORM 能够在单个应用程序中做它最擅长的事,这最终激发了我的兴趣,促使我在最近抽出时间来一探究竟。 在阅读大量文章和博客文章,与开发者聊过天并熟悉过 Dapper 后,我想与大家分享我的一些发现,尤其是和像我这样,可能听说过 Dapper 但并不知道它是什么或者并不知道它的工作原理的人分享,同时说说人们为什么这么喜欢它。需要提醒你的是,我根本不是什么专家。目前我只是为了满足我的好奇心而变得足够了解,并且希望激发你的兴趣,从而进一步探索。 为什么是 Dapper? Dapper 的历史十分有趣,它是从你可能再熟悉不过的资源中衍生的: Marc Gravell 和 Sam Saffron 在研究 Stack Overflow,解决此平台的性能问题时构建了 Dapper。考虑到 Stack Overflow 是一个流量极高的站点,那么必然存在性能上的问题。根据 Stack Exchange About 网页,在 2015 年,Stack Overflow 拥有 57 亿的网页浏览量。在 2011 年,Saffron 撰写过一篇关于他和 Gravell 所做的工作的博客文章,名为“我如何学会不再担忧和编写我自己的 ORM”(bit.ly/),这篇文章介绍了 Stack 当时存在的性能问题,该问题源于 LINQ to SQL 的使用。他在文中详细介绍了为什么编写自定义 ORM,其中 Dapper 就是优化 Stack Overflow 上的数据访问的答案。五年后的今天,Dapper 已被广泛使用并已成为开源软件。Gravell 和 Stack 及团队成员 Nick Craver 继续在 github.com/StackExchange/dapper-dot-net 上积极地管理项目。 ...

June 25, 2024

Entity Framework Core:一对多关系

当一个实体类型的任意数量的实体与相同或另一个实体类型的任意数量的实体相关联时,将使用多对多关系。 例如,Post 可以有多个关联的 Tags,并且每个 Tag 可以与任意数量的 Posts 关联。 了解多对多关系 多对多关系不同于一对多和一对一关系,因为它们不能仅使用外键以简单方式表示。 相反,需要其他实体类型来“联接”关系的两端。 这称为“联接实体类型”,并映射到关系数据库中的“联接表”。 此联接实体类型的实体包含外键值对,其中一对指向关系一端的实体,另一对指向关系另一端的实体。 因此,每个联接实体以及联接表中的每一行都表示关系中实体类型之间的一个关联。 EF Core 可以隐藏联接实体类型并在后台对其进行管理。 这允许以自然方式使用多对多关系的导航,从而根据需要在每一端添加或删除实体。 但是,了解后台发生的情况非常有用,以便其整体行为(尤其是映射关系数据库)有意义。 让我们从关系数据库架构设置开始,以表示帖子和标记之间的多对多关系: CREATE TABLE "Posts" ( "Id" INTEGER NOT NULL CONSTRAINT "PK_Posts" PRIMARY KEY AUTOINCREMENT); CREATE TABLE "Tags" ( "Id" INTEGER NOT NULL CONSTRAINT "PK_Tags" PRIMARY KEY AUTOINCREMENT); CREATE TABLE "PostTag" ( "PostsId" INTEGER NOT NULL, "TagsId" INTEGER NOT NULL, CONSTRAINT "PK_PostTag" PRIMARY KEY ("PostsId", "TagsId"), CONSTRAINT "FK_PostTag_Posts_PostsId" FOREIGN KEY ("PostsId") REFERENCES "Posts" ("Id") ON DELETE CASCADE, CONSTRAINT "FK_PostTag_Tags_TagsId" FOREIGN KEY ("TagsId") REFERENCES "Tags" ("Id") ON DELETE CASCADE); 在此架构中,PostTag 是联接表。 它包含两列:PostsId(指向 Posts 表的主键的外键)和 TagsId(指向 Tags 表的主键的外键)。 因此,此表中的每一行都表示一个 Post 和一个 Tag 之间的关联。 ...

June 23, 2024

Entity Framework Core:一对多关系

当单个实体与任意数量的其他实体关联时,将使用一对多关系。 例如,Blog 可以有多个关联的 Posts,但每个 Post 都只与一个 Blog 相关联。 本文档采用围绕大量示例展开的结构。 这些示例从常见情况着手,还引入了一些概念。 后面的示例介绍了不太常见的配置类型。 此处介绍了一个不错的方法,即了解前几个示例和概念,再根据特定需求转到后面的示例。 基于此方法,我们将从简单的“必需”和“可选”的一对多关系开始。 提示 可在 OneToMany.cs 中找到以下所有示例的代码。 必需的一对多 // Principal (parent) public class Blog { public int Id { get; set; } public ICollection<Post> Posts { get; } = new List<Post>(); // Collection navigation containing dependents } // Dependent (child) public class Post { public int Id { get; set; } public int BlogId { get; set; } // Required foreign key property public Blog Blog { get; set; } = null!; // Required reference navigation to principal } 一对多关系由以下部分组成: ...

June 21, 2024