网友语录 - 第13期 - 人类之所以进步,是因为下一代不听上一代的话

安子 尽量多发现身边那些笑点很低,很容易满足,无论何时看起来都是喜洋洋的人,并且尽量多的跟他们在一起,你会感觉到被滋养,被激发,被启迪。它们像炭火一样煲养你的生命,给你力量,带来喜悦,他们是真正的人间天使。(更重要的,只要你贴他们足够近,他们还有能力把你转化成他们的同类)


碧螺姑娘 突然间真实感受到了“人生是旷野”的具体意义。虽然风刀霜剑严相催,但就是要热热闹闹地去活着。


奧匈帝國小説家弗朗茨·卡夫卡(Franz Kafka)寫過一則微型小説叫《法律門前》。小説講的是:有個鄉下人走到一處敞開的大門前,但是看門人不讓他進去。鄉下人問,那他以後可不可以進去呢?看門人跟他説,以後有可能,但是現在不行。看門人還暗示他說,如果他實在想進去,可以試一試,不過裏面還有更多看門人守著其他大門,這些看門人一個比一個難纏。後來這個鄉下人就在這個大門前等了一輩子,就等有機會允許他進去。等到自己快要死的時候,鄉下人問:爲什麽一直沒有其他人要求進這個大門?看門人跟他說:因爲這個大門就是專門給你一個人開的,等你死了,大門就會關起來。


人生若梦为欢几何 有句话说的很好,你把生活当游戏,把周围所有的人当npc,就不会内耗了。


CarrieZ 人类之所以进步,是因为下一代不听上一代的话


…more

Implementing QuickFix/n Logging with NLog

Wen working with QuickFix/n ibrary , efficient logging is crucial for troubleshooting. Here's how to implement a custom logging solution that routes QuickFix logs through NLog to your ELK stack.

Key Components

  1. NLogAdapter: A custom adapter that implements QuickFix's ILog interface:
public class NLogAdapter(ILogger logger) : ILog
{
    private const string HeartbeatPattern = @"\x0135=0\x01";
    private static readonly Regex HeartbeatRegex = new(HeartbeatPattern, RegexOptions.Compiled);

    private static bool IsHeartBeat(string message) => HeartbeatRegex.IsMatch(message);

    public void OnIncoming(string message)
    {
        if (!IsHeartBeat(message))
        {
            logger.Info("Incoming: {Message}", message);
        }
    }
    // ... other implementations
}
  1. NLogQuickFixLogFactory: A factory class to create log instances:
public class NLogQuickFixLogFactory(ILog logger) : ILogFactory
{
    public ILog Create(SessionID sessionId) => logger;
    public ILog CreateNonSessionLog() => logger;
}

Implementation Steps

  1. Register Dependencies in your DI container:
builder.Services.AddSingleton<NLog.ILogger>(_ => LogManager.GetCurrentClassLogger());
builder.Services.AddSingleton<ILog, NLogAdapter>();
builder.Services.AddSingleton<ILogFactory, NLogQuickFixLogFactory>();
  1. Configure QuickFix to use the custom logger:
var initiator = new SocketInitiator(
    clientApp,
    storeFactory,
    sessionSettings,
    new NLogQuickFixLogFactory(quickfixLogger)  // Use custom logger injeted by ILog here 
);

Key Features

  • Heartbeat Filtering: Reduces log noise by filtering out FIX heartbeat messages
  • Structured Logging: Uses NLog's structured logging format for better parsing in ELK
  • Separation of Concerns: Cleanly separates QuickFix logging from application logging

Benefits

  1. Centralized logging in ELK stack
  2. Better debugging apabilities
  3. Reduced log volume through heartbeat filtering
  4. Consistent logging format across your application

Common NUnit `Assert` statements

Here’s a consolidated list of common NUnit Assert statements, categorized by their purpose. This should cover most of the common scenarios:


Basic Assertions

  • Equality:

    Assert.That(actual, Is.EqualTo(expected));
    Assert.That(actual, Is.Not.EqualTo(expected));
    
  • Boolean Conditions:

    Assert.That(condition, Is.True);
    Assert.That(condition, Is.False);
    
  • Null Checks:

    Assert.That(obj, Is.Null);
    Assert.That(obj, Is.Not.Null);
    

String Assertions

  • Contains:

    Assert.That(actualString, Does.Contain(substring));
    
  • Starts With / Ends With:

    Assert.That(actualString, Does.StartWith(prefix));
    Assert.That(actualString, Does.EndWith(suffix));
    
  • Empty or Not Empty:

    Assert.That(actualString, Is.Empty);
    Assert.That(actualString, Is.Not.Empty);
    
  • Matches Regex:

    Assert.That(actualString, Does.Match(regexPattern));
    

Collection Assertions

  • Contains Item:

    Assert.That(collection, Does.Contain(item));
    
  • Has Specific Count:

    Assert.That(collection, Has.Count.EqualTo(expectedCount));
    
  • Empty or Not Empty:

    Assert.That(collection, Is.Empty);
    Assert.That(collection, Is.Not.Empty);
    
  • Unique Items:

    Assert.That(collection, Is.Unique);
    

Numeric Assertions

  • Greater Than / Less Than:

    Assert.That(actual, Is.GreaterThan(expected));
    Assert.That(actual, Is.LessThan(expected));
    
  • Greater Than or Equal / Less Than or Equal:

    Assert.That(actual, Is.GreaterThanOrEqualTo(expected));
    Assert.That(actual, Is.LessThanOrEqualTo(expected));
    
  • In Range:

    Assert.That(actual, Is.InRange(lower, upper));
    

Type Assertions

  • Instance of Type:

    Assert.That(obj, Is.TypeOf<ExpectedType>());
    Assert.That(obj, Is.InstanceOf<ExpectedType>());
    
  • Assignable From:

    Assert.That(obj, Is.AssignableTo<ExpectedType>());
    

Exception Assertions

  • Throws Exception:

    Assert.Throws<ExpectedExceptionType>(() => { methodCall(); });
    
  • Throws Specific Exception with Condition:

    var ex = Assert.Throws<ExpectedExceptionType>(() => { methodCall(); });
    Assert.That(ex.Message, Does.Contain("expected message"));
    

Miscellaneous

  • Same Instance:

    Assert.That(actual, Is.SameAs(expected));
    Assert.That(actual, Is.Not.SameAs(expected));
    
  • Applies a Condition:

    Assert.That(collection, Has.Some.Matches<ExpectedType>(item => item.Condition));
    
  • Delayed Constraints (Asynchronous):

    Assert.That(() => condition, Is.True.After(500).PollEvery(50));
    
  • Group related assertions together to improve readability and reporting:

    Assert.Multiple(() =>
    {
        Assert.That(okResult, Is.Not.Null, "okResult should not be null");
        Assert.That(okResult.Value, Is.TypeOf<string>(), "Value should be of type string");
    });
    

= null! vs. = string.Empty: Best Practices for Model Class Initialization

The choice between = null! and = string.Empty depends on the context and the intent of the code. Here's a breakdown to help you decide:


= null!

When to Use:

  1. You Intend to Initialize the Field Later:

    • Use = null! when the property or field is expected to be set by a constructor, a method, or dependency injection after the object is created.

    • Example:

      public string Name { get; set; } = null!;
      
    • Why: null! tells the compiler to trust you that the value will be assigned before being accessed.

  2. Avoid Premature Default Values:

    • If a default value like string.Empty doesn't make sense for the context, null! keeps the intent clearer.
  3. For Models or Data Contracts:

    • In cases where fields are expected to match a schema or be deserialized from external sources, it might be better to indicate "unknown until set."

    • Example:

      public string Username { get; set; } = null!; // Will be deserialized later
      

= string.Empty

When to Use:

  1. Default Values Are Meaningful:

    • Use = string.Empty when an empty string is a valid and reasonable default.

    • Example:

      public string Name { get; set; } = string.Empty;
      
    • Why: This avoids null-checking or potential runtime errors when accessing the property.

  2. Simpler to Work With:

    • If the field/property is commonly accessed and null is not a meaningful value in your application, an empty string simplifies the logic (avoids extra null-checks).
  3. UI or Display-Friendly Fields:

    • For fields used in UI contexts, empty strings often make more sense than null:

      public string Description { get; set; } = string.Empty;
      

Key Differences

Aspect = null! = string.Empty
Purpose Indicates value will be set later. Provides an immediate, valid default.
Compiler Warnings Suppresses nullability warnings (unsafe). Avoids nullability warnings entirely.
Clarity Explicitly states "not initialized yet". Implies "initialized to empty value now".
Best Fit Models, external contracts, DI patterns. Readily usable properties or fields.

When to Avoid = null!

  • When it's unclear who or what will initialize the property.
  • When using null might lead to accidental runtime errors.
  • When the property will be frequently accessed before initialization.

Recommendation

  • Use = string.Empty when empty strings make sense as defaults and simplify code.
  • Use = null! when initialization will occur later, and null isn't a valid or meaningful runtime value.

You know who is the real author of this article, don't you? :P

网友语录 - 第12期

这里记录每周值得分享的网友文字,我的网摘和书摘。一般在周六发布。

愚兄 人很多懊恼来自于对他人的“怒其不争”,也就是特喜欢当爹育人。很多时候对方根本不想也无法被教育,要欣喜于这世界有花,也接纳这世界有蛆。(世间万物,各有各的活法)


书摘 《暮色将尽》

我还从没认真地使用过自己的双手,当然绣花除外,这个我很在行。想象一下,如果能用自己的双手做个书架,那该多么有益,又多么令人开心啊!我真的为此感到遗憾。

因此,总的来说,我这一生,一共有两件最主要的憾事:内心深处有一个冷酷的点,以及懒惰(缺乏行动力其实也不乏胆怯的因素,但我觉得懒惰比胆怯的比重大些)。这两件憾事真实存在,但并没有怎么太折磨我,我也没觉得该常常反思。止于此就行了吧,因天天看着不好的一面是相当无聊的事。我不觉得挖掘过去的内疚对老年人有什么意义,历史已经无法改变了。

......

看看她说的话,她说她到现在依然记得在集中营里唯一善良的纳粹邻居,在以色列感受到的令人心灵颤料的自由,以及她如何热爱英国、热爱英国人,更重要的是,她到现在依然嗜好钢琴演奏,每天都弹三小时。她曾说过,“工作是人类最棒的发明••••它让你感到快乐,因你在做事情”,她和玛丽•路易斯•莫泰希茨基一样令人惊异,而她是天生就有创造力的典型。她沉醉于生活的美妙之中,并非由于宗教的激发,“开始是这样的,我们生来就有好的一面,也有坏的一面,每个人,每一个人都是这样的。然后你会遇到激发你内心好或坏的不同境遇,我相信,这就是为什么人们要发明宗教的原因”,因此她很尊重宗教里饱含的希望,尽管她的内心未必需要宗教的支持。她身上有一种不同寻常的好运,天生就具备强有力地朝向乐观主义的本性,不论经历了怎样的际遇,她依然会这样说:“生命是美丽的,如此美丽。而一个人越老,就越能察觉到这一点。当你老了,你思考,你记忆,你关切,你明了。你因为一切而深怀感激,为一切。”她还说:“我了解所有事情坏的一面,但我只看好的一面。”

.....

我是在狗的陪伴下长大的,所以不太理解为什么有些人不喜欢狗。这种动物被人类驯养的历史很久了,与人生活在一起似乎天经地义,如虎入丛林一般自然。它们已成为人类能透彻了解其情感的唯一动物种群。它们的情感与人类何其相似,只是看起来形式简单些罢了。当一只狗焦虑、愤怒、饥饿、迷惑、快乐或充满爱意时,它将这些情绪以最纯洁的形式呈现出来,我们也能感受得到,只不过人类的这些情感早被日益增长的复杂人性扭曲变形了。狗和人类因此在简单却深刻的层面彼此相通,我多想再养一只黑色绒脸小哈巴狗,重新体验这一切啊

......

我们非常清楚生命是依照生物规律而不是个体规律运作的,个体出生、长大、生儿育女、凋零死亡让位给后来者。不管人类做着怎样的白日梦,也无法幸免这样的命运。当然,我们想要尽力延长凋零过程,以至于有时候凋零甚至比成长所经历的时间还长,因此,在这一过程中会遭遇什么,如何能尽力过好这一凋零的时光,确实值得深思。现在有这么多关于保持青春的书,还有更多有关生儿育女详尽的、实验性的经验分享,但有关凋零的记录却不多见。而我,正行走在这一凋零的路程当中,我的神经刚刚经历了小狗事件和树蕨事件,倍感痛楚,于是我问自己:“为什么我不来记录?”因此,我写了这本书。

......

不信神说明什么?缺乏想象力,还是缺乏勇气?或仅是一种遗传所赋予的性情模式?前两种情况在有神论或无神论的群体中均能发现,第三种情况只不过用家族史将这个问题回避过去罢了。虔诚但文化不高的人常觉得我的这种辩解是一种放肆,是淘气任性、拒绝自我节制的行为,但实际上不管信不信神,人们一样能勤勉地履行外界赋予我们的制约和责任,并和他人一起分享这个世界。对无神论者而言,答案可能很简单,尽管说起来有点令人难为情:他不信,只是因为他觉得自己比信神的兄弟聪明智慧。不过他那信神的兄弟从相反的角度,势必也是同样的想法,那么谁可以做中间调停人?我想我们必须接受这个事实,即关于这个问题,世界上存在着两种人。


西瓦 “家居生活的舒适与整洁无关。若非如此,则每个人都可能住在室内设计与建筑杂志刊出的那些不具生气、全无人味的房屋中。这些整理得毫无瑕疵的房间所欠缺的,或者说摄制这些房间的摄影师所刻意去除的,是经人住用的一切证据。”《家的设计史》


…more