#48 Assertions and Design by Contract, Part-2

Поделиться
HTML-код
  • Опубликовано: 19 мар 2023
  • In this second lesson about assertions and Design by Contract (DBC), you'll see how to practically apply them in embedded systems.
    Contents with Timestamps:
    -------------------------
    0:45 Agenda for the previous Part-1 and today's Part-2
    1:00 Embedding assertions (the qassert.h header file)
    1:45 qassert.h code review (using Doxygen documentation)
    2:35 Q_ASSERT_ID() macro implementation
    3:53 Q_ASSERT_ID() macro use
    4:34 Q_DEFINE_THIS_MODULE() macro
    4:52 no-return semantics of the Q_onAssert() handler
    5:37 DBC elements: Preconditions, Postconditions, Invariants
    6:57 Errors and the use of Q_ERROR_ID() macro
    7:05 The Q_onAssert() assertion handler
    8:12 Resetting the target in the assertion handler
    8:37 Use of fault-injection for testing assertion failures
    8:59 Assertions & Throwing Exceptions
    9:48 Hardware assertions
    10:28 Avoiding "denial of service"
    11:06 Impact of Assertions
    11:32 NASA JPL guidelines about assertion density
    11:48 Microsoft Research study of assertions and code quality
    12:25 Transformative impact of assertions on development
    13:15 Demoralizing effects of "defensive programming"
    13:32 Disabling assertions in the final product
    14:45 Disabling assertions in the assertions-as-fuzes analogy
    14:52 Disabling assertions in the assertions-as-guardrails analogy
    15:08 Disabling assertions in the assertions-as-insurance analogy
    End Notes:
    ----------
    Companion web page to this video course
    www.state-machine.com/video-c...
    Project download for this lesson:
    www.state-machine.com/course/...
    GitHub repository for projects for this video course:
    github.com/QuantumLeaps/moder...
    Transcript of this lesson:
    www.state-machine.com/course/...
    References resources:
    ---------------------
    Key Concepts: Design by Contract
    www.state-machine.com/dbc
    Bertrand Meyer, “Applying Design by Contract”, IEEE Computer, 1992
    www.state-machine.com/doc/May...
    Miro Samek, “An Exception or a Bug?”, C/C++ Users Journal, June 2003
    www.state-machine.com/doc/Sam...
    Quantum Leaps, Design By Contract (DBC) for Embedded C and C++, GitHub
    github.com/QuantumLeaps/DBC-f...
    Music credits:
    --------------
    The background music comes from:
    www.bensound.com/royalty-free...
  • НаукаНаука

Комментарии • 41

  • @deepakr8261
    @deepakr8261 Год назад

    Great video. But would you recommend leaving asserts ON even(in release builds) for safety critical systems? Wouldnt defensive programming be better in such systems as they dont crash the system(and possibly let the safety monitors take actions like limp home mode when error manifest down the line)

    • @StateMachineCOM
      @StateMachineCOM  Год назад +3

      There is a lot to unpack in this question. But first, I recommend leaving assertions ON *especially* in safety-critical systems. However, that does NOT mean "crashing the system." On the contrary: leaving assertions ON provides the last line of defense against "dangerous modes of failure" (a term from IEC 61508) to put the system in Fail-Safe mode (whatever that means in the particular case). You lose this chance when you disable assertions. Second, there seems to be a misunderstanding of what "defensive programming" means. Behavior like "limp mode" requires very *deliberate* design as part of handling this exceptional condition. Such deliberate design is the exact opposite of "defensive programming," which just hides problems (like returning a bogus value instead of dividing by zero). It is somewhat naive to believe that any coherent behavior (like the "limp" mode) can somehow emerge from such "defensive programming." --MMS

  • @wondererasl
    @wondererasl Год назад +1

    Man, you can stick to one thing for 10+ years, this is also another valuable lesson for me personally. Waiting for the next!

    • @StateMachineCOM
      @StateMachineCOM  Год назад +2

      Embedded programming is a *deep* subject, and you got to stick with it for longer to get good at it. It takes 10,000 hours to become good at anything. --MMS

    • @damiengates7581
      @damiengates7581 11 месяцев назад

      Eh, really appreciate the videos, but they didn't come out over 10 years because of perseverance or something..

    • @StateMachineCOM
      @StateMachineCOM  11 месяцев назад +2

      @@damiengates7581 Actually, the "Modern Embedded Programming" video course is a result of frustration. In the embedded programming community almost every term means completely different things to different people. For example, you say "state machine", and everyone means something else. You say "event-driven", and again, there is no common understanding. Same goes for "assertion-based programming", "concurrency hazards", "encapsulation", etc.

  • @almari3954
    @almari3954 Год назад +4

    Most of my coworkers think that asserts and tracing/logging is not that important and a debugger is the only thing they need and they only use the debugger for step-by-step debugging. For a long time I was of the same mind, but now I think that longer term good assertions and tracing save a lot of time. Sometimes it's even not possible to reach the final, good design without them.

    • @StateMachineCOM
      @StateMachineCOM  Год назад +4

      Yes, exactly. Assertions seem to be one of the most misunderstood, unappreciated, and underutilized techniques in programming (not just embedded). That's precisely why I made these videos. I hope that at the very least developers will become *aware* that such a technique even exists. --MMS

  • @twenty-fifth420
    @twenty-fifth420 4 месяца назад +1

    I feel like this is the one video as an intermediate I needed to finish. It defines a certain style and practice for writing secure, and scalable code safely. I also am glad you used C examples, mostly because I am here for game development and smaller SOCs like piboards. Everytime someone I work with asks about software with these devices in mind, will probably link this video series.
    Small aside, but you can model your contracts based on hardware expectations as well such as for x86 and also ARM with different assertions and conditions, right? I also think this because the differences in assembly possibly needed for things like registers, buses, memory management etc etc. Just want to cover all my bases. Personally am only developing on x86 at the moment, but eventually will get an SBC/SOC board.
    Finally, I am using Nim/Swift, so I am curious how well these modern languages will work in embedded or in my use case smaller computer boards; but I guess the only way to find out is to try, and see if it is a pass or fail.
    Edit: Also, I am sure Piboards and ARM SOCs are not quite 'embedded', don't want to go away from this with that in mind. I considered embedded a range from smaller chips found in controller for example to something at most like a SBC board with a full motherboard of features.

    • @StateMachineCOM
      @StateMachineCOM  4 месяца назад +1

      Assertions (as part of Design by Contract philosophy) are applicable to any software, not just embedded and not just "small" systems. However, the effective use of assertions requires two critically important considerations. First, assertions must be used only for errors (bugs) and never for "exceptional conditions". Second, assertion failure handler must be carefully designed and *tested* to bring the system to a "safe state" (whatever that means for a given system).
      Also, assertions *are* the recommended practice, and indeed a cornerstone, of safety-critical systems (e.g., IEC 61508 standard recommends "Failure Assertion Programming" practice). Safe software must either operate correctly, or fail *safely*. The worst possible (and unacceptable) scenario is when the software keeps operating unsafely. Unfortunately, this is precisely what happens when assertions are turned off in the production release.
      Finally, regarding Nim/Swift, there is a discussion of the QP frameworks on the Nim forum: forum.nim-lang.org/t/5137 .
      --MMS

  • @adelmamin2
    @adelmamin2 Год назад +2

    Disabling asserts in release builds is like learning to drive and using seat belt and then stop using it once you get driving license :)

    • @StateMachineCOM
      @StateMachineCOM  Год назад +2

      This reminds me of the quote from Tony Hoare (one of the founding fathers of computer science), who used to say: "Disabling assertions in production is like using a lifebelt during exercise but not bothering with it for the real thing".

  • @almari3954
    @almari3954 Год назад +2

    Sometimes in initial phase of development it's difficult to
    to judge if a condition is exceptional, or should be treated
    as an error. I frequently see junior developer code
    with return codes totally ignored etc. I would argue that
    in those cases, even if the conditions finally turn out to be just exceptions,
    putting in assertions is also beneficial.

    • @StateMachineCOM
      @StateMachineCOM  Год назад +5

      Sure, do whatever helps you during development. But in the *production* version you release to customers, assertions become as important as the rest of the code. (This assumes that you leave assertions enabled in the production release.) In my programming practice, I actually spend more time thinking about assertions and *testing* that they actually catch errors than the regular code. In my mind, treating assertions as second-class, throw-away code misses a huge opportunity. I hope that these comments make sense to you. --MMD

    • @almari3954
      @almari3954 Год назад

      @@StateMachineCOM yes, this makes a lot of sense. Thank you.

  • @ahmed.elfeqy
    @ahmed.elfeqy Год назад +1

    Amazing Video as always, maybe they choose to disable assertions to prevent "unnecessary” bloated code. but I totally agree with you and if they think that these simple assert conditions bloat the code, they should have considered them in the original system design in the first place.

    • @StateMachineCOM
      @StateMachineCOM  Год назад +2

      Yes, I agree that many developers believe that assertions add a lot of overhead to the code. But in practice, the overhead is quite small and often pays for itself because (as mentioned in the video) assertions *eliminate* a lot of "defensive code". --MMS

  • @jankeshchakravarthy9389
    @jankeshchakravarthy9389 Год назад +1

    In my experience, the asserts are of two types. Debug asserts and prod_asserts. As name suggests the debug asserts are used during development till it system gets maturity and are disabled from final production. The disabling of the debug assert will lead to change in the code execution time and some defects may pop out. That is the reason, the debug asserts are disabled few months earlier to release so that, it gets tested enough before release. My two cents. -:)

    • @StateMachineCOM
      @StateMachineCOM  Год назад +3

      As I said in the other comments, do whatever helps you in debugging. But from my experience, introducing "debug assertions" alongside "production assertions" is a slippery slope. (The next level is adding a "severity level" in assertions and then disabling assertions only up to a given level.) The problem with this approach is that assertions stop being taken seriously but rather as some temporary and throw-away code. With this attitude, people lose confidence in assertions and don't trust them to really perform drastic actions. Also, developers are confused as to which assertions are really "worthy" leaving in the production code and which to turn off. I hope you see my point. --MMS

  • @BerthaProt
    @BerthaProt Год назад

    Again Great video, one point, I am not sure to follow: the _ID suffixe, OK lane can change but not once compiled. Is there any added value to use _ID for others tools in the futur ? I have trouble seeing in a real case the benefit of adding _ID, am I missing something ? You are the best !

    • @StateMachineCOM
      @StateMachineCOM  Год назад +1

      Good point that needs to be explained. So, if the assertions can bring down the whole system, they are apparently important. Such code needs to be TESTED. To do so, you need to make the assertion fail (e.g., by "failure injection") and then you must verify that the *right* assertion has failed. Now, how do you identify the *right* assertion in your test? If you identify it by the line number, you'd have to change the test every time the lines shift in your code. Such tests would be then very unstable. The use of the assertion-IDs helps in writing *stable* tests because these IDs don't shift. I hope this makes more sense now. --MMS

  • @AliNormukhamedov
    @AliNormukhamedov Год назад

    Thank you for all the videos ! Would it be possible to make one to compare some of the different RTOSes available on the market and explain the difference with Linux Embedded RTOS (ex VxWorks) ? Thank you !!!

    • @StateMachineCOM
      @StateMachineCOM  Год назад

      A comparison like this would be tricky and necessarily biased. But such comparisons have been already done. Here, I would recommend a blog post "Are all RTOSes the Same?" by Michael Barr: embeddedgurus.com/barr-code/2008/01/are-all-rtoses-the-same . Having said that, I do plan some future lessons in this course to cover various types of schedulers, but these would not be the traditional RTOSes or embedded Linux offerings you're requesting. (Traditional RTOSes have been discussed in lessons 22-28, see ruclips.net/p/PLPW8O6W-1chyrd_Msnn4LD6LBs2slJITs ). --MMS

  • @jankeshchakravarthy9389
    @jankeshchakravarthy9389 10 месяцев назад

    I absolutely agree for not disabling the assert in the final firmware. But in my experience, I implemented two levels of asserts. 1. assert_debug 2. assert_release. The debug asserts are disabled(tapered slowly) few months before release. The release asserts are critical ones and acts like guard rails and debug asserts are like training wheels.

    • @StateMachineCOM
      @StateMachineCOM  10 месяцев назад

      Yes, I've seen the distinct "debug-assertions" and "release-assertions". I've also seen a "severity-level" parameter added to assertions and then an option to disable assertions only up to a certain level. All of this is a bit slippery slope leading to low-quality assertions that people don't take seriously. Could you give me an example of a "debug-assertion" that would NOT be good enough as a "release-assertion"? In my opinion, assertions are an inherent part of the code (the design contracts). They should be developed and *tested* along with the code they protect. Then they should be released, exactly as they've been tested. --MMS

    • @jankeshchakravarthy9389
      @jankeshchakravarthy9389 10 месяцев назад

      @@StateMachineCOM - Here are some examples of debug asserts. 1. a routine checking the 32byte alignment of address that is returned by another routine.
      2. checking the command/packet size. 3. Checking the execution time of a routine. The data point is, during the product qualification.
      The main reason for removing debug assert from release code is - the asserts add cpu overhead and data shows that system never hit these asserts during hours of qualification and some of them are purely debug purpose.

  • @ashrafkamel1287
    @ashrafkamel1287 Год назад +1

    Great video!
    what do you plan to cover next?

    • @StateMachineCOM
      @StateMachineCOM  Год назад +2

      In the next segment of lessons, I plan to go back to the fundamentals and real-time architectures. Specifically, I'd like to explain the various real-time kernels that can be used to run event-driven systems, because the traditional RTOS is not the only option here. It turns out that the non-blocking, run-to-completion characteristics of event-driven systems allow us to use *simpler* and more efficient real-time kernels than the traditional RTOS. Stay tuned! --MMS

    • @ashrafkamel1287
      @ashrafkamel1287 Год назад +1

      @@StateMachineCOM Many thanks for your reply.
      That sounds interesting.
      If I may, I would recommend to also revisit the Event driven design pattern and QP framework
      with more relatable projects rather than the Time bomb we had.
      Although I am keen on adapting that pattern at my team, I really still struggle to start, even with projects I already made
      I have the flat State Machines for them, the modules, everything.
      but I don't know how to start
      creating the Active Objs
      what is difference between signals and events
      and so
      Huge part is because I didn't read the Docs yet.
      but I am sure this part needs revisit on the channel.
      and if you can spare advise here on comments
      it would be appreciated

    • @damiengates7581
      @damiengates7581 11 месяцев назад

      How can it be so difficult?

    • @ashrafkamel1287
      @ashrafkamel1287 11 месяцев назад

      @@damiengates7581 did you try it?
      If you did successfully
      I would like to hear your experience

  • @jankeshchakravarthy9389
    @jankeshchakravarthy9389 Год назад

    Hi Miro - Is it possible to have a video that describe different terms firmware, embedded software, and real time system? I know it is very very basic question, but there is confusion among the engineers.

    • @StateMachineCOM
      @StateMachineCOM  Год назад

      The concept of "real-time" has been explained in lesson#26 "What is real-time?" ruclips.net/video/kLxxXNCrY60/видео.html . But regarding the distinction between "firmware" and "embedded software", I don't quite see the difference, so I can't explain this aspect. --MMS

  • @BinGanzLieb
    @BinGanzLieb Год назад +1

    what is your opinion in using exceptions on embedded systems?

    • @StateMachineCOM
      @StateMachineCOM  Год назад +2

      Good question. First of all, I see the mechanism of throwing and catching exceptions (if this is what you mean) as part of handling *exceptional conditions* with the intent to continue execution. As I explained in the video at 8:50, in my view throwing exceptions should *NOT* be used to "handle" errors/bugs because it's overkill and additional risk for that. Now, throwing exceptions in exceptional conditions has obviously value when you have deep function call trees, so unwinding the call stack gives you a chance to reasonably "handle" an exception. This has some merit, perhaps, in sequentially written code (e.g., with traditional RTOS). But in *event-driven* code, you don't have much stack to deal with because the stack is constantly discarded after processing each event. In other words, there is no much *context* on the stack and instead the context is in the *state* of the state machine. For that, throwing exceptions is not that helpful. instead, an exceptional condition should be handled as a separate *state* of the state machine. Also, please google for the article "Exception Handling: A False Sense of Security" by Tom Cargill. --MMS

    • @BinGanzLieb
      @BinGanzLieb Год назад

      ​@@StateMachineCOM thank you. i will read that referenced article

    • @almari3954
      @almari3954 Год назад

      @@StateMachineCOM yeah, and the bubbling up of unhandled events in hierarchical SM is somewhat similar to throwing exceptions.

  • @BinGanzLieb
    @BinGanzLieb Год назад

    Download Link doesnt work.

    • @StateMachineCOM
      @StateMachineCOM  Год назад

      Thanks for reporting. I corrected the download link in the video description. The links on the companion page ( www.state-machine.com/video-course ) seem to be correct. --MMS

  • @GeorgeSmith-vg7uz
    @GeorgeSmith-vg7uz 9 месяцев назад

    This series started 10 years ago. Is IAR Embedded Workbench for ARM still available? On their website it is not available anymore which is understandable after so many years.

    • @StateMachineCOM
      @StateMachineCOM  9 месяцев назад

      I plan to add the ARM/KEIL uVision projects to all downloads, including the older lessons released originally with IAR. This will allow anybody interested to use ARM/KEIL toolset instead of IAR. This work will be completed soon. The downloads will be available in the usual locations:
      - www.state-machine.com/video-course
      - github.com/QuantumLeaps/modern-embedded-programming-course