<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: John "Fitzy" DeLancey</title>
    <description>The latest articles on Forem by John "Fitzy" DeLancey (@fitzycodesthings).</description>
    <link>https://forem.com/fitzycodesthings</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F443815%2F5bf9fe67-d531-4425-82d0-9b6550762264.png</url>
      <title>Forem: John "Fitzy" DeLancey</title>
      <link>https://forem.com/fitzycodesthings</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/fitzycodesthings"/>
    <language>en</language>
    <item>
      <title>Help me pick a modern report writing tool/package for DotNet?</title>
      <dc:creator>John "Fitzy" DeLancey</dc:creator>
      <pubDate>Sat, 21 Nov 2020 06:11:37 +0000</pubDate>
      <link>https://forem.com/fitzycodesthings/help-me-pick-a-modern-report-writing-tool-package-for-dotnet-2h55</link>
      <guid>https://forem.com/fitzycodesthings/help-me-pick-a-modern-report-writing-tool-package-for-dotnet-2h55</guid>
      <description>&lt;p&gt;So I find myself - somehow for the first time - needing to onboard a more serious report writing tool/package/library for my fintech client.&lt;/p&gt;

&lt;p&gt;We're a Dot Net company primarily focused on ASP.NET Core banking related applications.&lt;/p&gt;

&lt;p&gt;Basic needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate BIG (200-300 printed page), primarily tabular data reports (with the ability to add more data visualization over time)&lt;/li&gt;
&lt;li&gt;Ability to export reports/data to Excel &amp;amp; PDF&lt;/li&gt;
&lt;li&gt;Summarize data/visualizations for automated display on the web&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So far I've seen example packages from Telerik, DevExpress, and SyncFusion that LOOK like they're along the lines of what we need, but given the expense of them, I'd like to have a solid idea what I'm getting into.&lt;/p&gt;

&lt;p&gt;I've also seen PowerBI and Tableau and have no idea what they really are or if they might be a good fit here.&lt;/p&gt;

&lt;p&gt;Any thoughts/feedback is MOST appreciated. Thanks!&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Let's Talk About Mental Health | Announcing The Continue Project</title>
      <dc:creator>John "Fitzy" DeLancey</dc:creator>
      <pubDate>Tue, 03 Nov 2020 18:59:11 +0000</pubDate>
      <link>https://forem.com/thecontinueproject/let-s-talk-about-mental-health-announcing-the-continue-project-li1</link>
      <guid>https://forem.com/thecontinueproject/let-s-talk-about-mental-health-announcing-the-continue-project-li1</guid>
      <description>&lt;p&gt;It's time. Let's talk about mental health as technologists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch the Announcement
&lt;/h2&gt;

&lt;p&gt;You can catch the full replay of the announcement (a little over 30 minutes) right here:&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/HL-TtumhPdo"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Wanna skip to the good parts?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://youtu.be/HL-TtumhPdo?t=363"&gt;Official Announcement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtu.be/HL-TtumhPdo?t=524"&gt;Giveaway Details ($500+)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Just looking for the giveaway link? Here ya go (but do read on!): &lt;br&gt;
&lt;a href="https://gleam.io/GN1cM/the-continue-project-kickoff"&gt;Enter the Giveaway&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's this all about then?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;We are developers, engineers, and technologists who recognize the importance of mental health in our lives and support each other with resources and space for discussion as colleagues and friends.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While the stigma around discussing our mental health as humans has steadily decreased, I feel like we tech people still just don't talk about it enough.&lt;/p&gt;

&lt;p&gt;I don't even necessarily think it's to do with the stigma so much as it's that we tend to be solitary by nature. We (or at least I) like to hole up and get stuck into our code or projects and shut the "real world" out.&lt;/p&gt;

&lt;p&gt;So what happens when we DO need help?&lt;/p&gt;

&lt;p&gt;When we hit burnout?&lt;/p&gt;

&lt;p&gt;When impostor syndrome shuts us down?&lt;/p&gt;

&lt;p&gt;When we become depressed or anxious?&lt;/p&gt;

&lt;p&gt;Who do we turn to when our entire modus operandi is to put our headphones on and shut the world out?&lt;/p&gt;

&lt;p&gt;For too many, for too long, the answer has been no one. We ignore it until it can't be ignored, and then we're down for the count. Our work suffers, our relationships suffer, and we suffer.&lt;/p&gt;

&lt;p&gt;THAT'S what this project is about. &lt;/p&gt;

&lt;h3&gt;
  
  
  First, foremost, and always, this is a community in which we are free to discuss these issues and encouraged to support each other in pursuit of better mental health.
&lt;/h3&gt;

&lt;p&gt;From coping skills to avoiding burnout and impostor syndrome to just needing someone to hear us, the Continue Project is for every developer, engineer, and technologist who ever needs the support of people who get it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to Find Us
&lt;/h2&gt;

&lt;p&gt;You can join the community in a variety of places around the web.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://continueproject.com"&gt;The Continue Project Homepage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://discord.gg/KMQUHZQpjd"&gt;Our Discord Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/continueproj"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.facebook.com/thecontinueproject/"&gt;Facebook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/thecontinueproject"&gt;Dev Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/orgs/The-Continue-Project"&gt;Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Find a comfy spot and join the discussion.&lt;/p&gt;

&lt;h2&gt;
  
  
  You mentioned a giveaway?
&lt;/h2&gt;

&lt;p&gt;I did!&lt;/p&gt;

&lt;p&gt;To celebrate the launch of the project, we're giving away $500+ of "stuff." Entries are open through &lt;strong&gt;November 30th, 2020.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First prize&lt;/strong&gt; (1 winner) will receive a &lt;em&gt;1 year subscription to Pluralsight&lt;/em&gt; AND &lt;em&gt;a piece of "merch" of your choice&lt;/em&gt; shipped anywhere in the world we can reach.&lt;/p&gt;

&lt;p&gt;(I chose the Pluralsight subscription, by the way, because one of my favorite ways to get out of my head is to learn something new.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Four other winners&lt;/strong&gt; will also receive a piece of merch of their choice.&lt;/p&gt;

&lt;p&gt;I'm finalizing the initial designs for that merch and will certainly share them out ahead of time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To enter the kick-off giveaway, just visit the link below and enter with any or all of the available options.&lt;/strong&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://gleam.io/GN1cM/the-continue-project-kickoff"&gt;&amp;gt;&amp;gt; ENTER THE GIVEAWAY &amp;lt;&amp;lt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The goal, obviously, is to help spread the word as far and wide as possible. &lt;/p&gt;

&lt;p&gt;So anywhere you find a developer or engineer or technologist who could benefit from this space (I hope that's all of us), share the links. We never know who we might save from crisis or even just a bad day that could be made better if only they'd found us.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;I'm thrilled to get this off the ground. I know how important my network of friends and confidants has been and is to me when I'm going through these things, and I'm proud to be working with a number of other technologists, content creators, and friends to make that available to others.&lt;/p&gt;

&lt;p&gt;I hope you'll join us. I hope you'll ask when you need help. I hope you'll share the resources you've cultivated on your journey. I hope you'll lend an ear to our friends who need to be heard. &lt;/p&gt;

&lt;p&gt;I hope we'll all wake up, day after day, more at peace with ourselves and the lives we lead.&lt;/p&gt;

&lt;p&gt;Thank you.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>mentalhealth</category>
      <category>developer</category>
    </item>
    <item>
      <title>What is Developer Relations? An Interview with Twilio Developer Evangelist @LaylaCodesIt</title>
      <dc:creator>John "Fitzy" DeLancey</dc:creator>
      <pubDate>Fri, 16 Oct 2020 19:09:47 +0000</pubDate>
      <link>https://forem.com/fitzycodesthings/what-is-developer-relations-an-interview-with-twilio-developer-evangelist-laylacodesit-n5b</link>
      <guid>https://forem.com/fitzycodesthings/what-is-developer-relations-an-interview-with-twilio-developer-evangelist-laylacodesit-n5b</guid>
      <description>&lt;p&gt;As I explore options for the next phase of my career, I've grown more and more curious about the emerging role of developer advocates in the software engineering world. &lt;/p&gt;

&lt;p&gt;In this interview, I discuss the role with Layla, a developer evangelist for Twilio. Layla has her own &lt;a href="https://www.twitch.tv/laylacodesit"&gt;livecoding stream on Twitch&lt;/a&gt;, is a Microsoft MVP, and was recently elected to the board of the .NET Foundation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch the Interview
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/OyE5B4PbrOA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Covered
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Layla's unique path into software development &lt;/li&gt;
&lt;li&gt;What Developer Relations "is" and the two big roles: advocate and evangelist (and how they differ)&lt;/li&gt;
&lt;li&gt;How Twilio built an advocate-centric business around a large team of developer relations specialists&lt;/li&gt;
&lt;li&gt;Various approaches to developer advocacy content creation from documentation to live streaming on "official channels" vs person channels, etc.&lt;/li&gt;
&lt;li&gt;The role of developer AMBASSADORS - community members who are passionate about a product and are then supported by the company&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And MUCH more.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are your thoughts or questions about DevRel?
&lt;/h2&gt;

&lt;p&gt;This is an exciting niche within the software development world. I feel like I was built for it in a lot of ways, and I'm definitely curious to meet more developer advocates/evangelists and hear about their experiences!&lt;/p&gt;

&lt;p&gt;I also really liked getting to have a conversation with a developer who's daily work life is so different from my own. May do more of these.&lt;/p&gt;

&lt;p&gt;(&lt;a href="https://twitch.tv/fitzycodesthings"&gt;Follow me on Twitch&lt;/a&gt; to catch 'em live when I do. 😁)&lt;/p&gt;

&lt;p&gt;Until next time! &lt;br&gt;
- John&lt;/p&gt;

</description>
      <category>career</category>
      <category>learning</category>
      <category>developer</category>
    </item>
    <item>
      <title>CoreLMS: Custom Validation, Razor Pages, DTOs, and First UI Working!</title>
      <dc:creator>John "Fitzy" DeLancey</dc:creator>
      <pubDate>Fri, 18 Sep 2020 22:07:13 +0000</pubDate>
      <link>https://forem.com/fitzycodesthings/corelms-custom-validation-razor-pages-dtos-and-first-ui-working-2cf</link>
      <guid>https://forem.com/fitzycodesthings/corelms-custom-validation-razor-pages-dtos-and-first-ui-working-2cf</guid>
      <description>&lt;p&gt;Made some good progress this week.&lt;/p&gt;

&lt;p&gt;Most of it was OFF stream, but hey. That's what the record button's for. 🤣&lt;/p&gt;

&lt;p&gt;Started by dropping in some custom validation logic I've been messing with, then replaced the MVC project with a Razor Pages project (and fumbled around with scaffolding forever), then took a break and figured out how to tackle that issue, drop in DTOs, and get the first UI actually working.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get the Git
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/FitzyCodesThings" rel="noopener noreferrer"&gt;
        FitzyCodesThings
      &lt;/a&gt; / &lt;a href="https://github.com/FitzyCodesThings/core-lms" rel="noopener noreferrer"&gt;
        core-lms
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      An open source online learning management system project in ASP.Net Core MVC. Explores many best practices and patterns in modern software development.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Watch the Replay Redemption Video
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/qWkV4xJk8IQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Validation
&lt;/h2&gt;

&lt;p&gt;If you've been following along, you may remember from waaaay back in August (23 years ago I believe) that I was wrestling with how to implement validation across the system in a way that repeated as little code as possible.&lt;/p&gt;

&lt;p&gt;After some experimenting, I landed on an approach that I'm happy with (inspired by Hassan Habib's &lt;a href="https://github.com/hassanhabib/OtripleS" rel="noopener noreferrer"&gt;OtripleS project&lt;/a&gt; as so many things I do are).&lt;/p&gt;

&lt;p&gt;The approach lets us utilize the built in Data Annotations validation feature that's used automatically by ASP.Net Core, but in our business logic and in a unit testable way.&lt;/p&gt;

&lt;p&gt;I demonstrate how the logic works (along with the tests, of course) in &lt;a href="https://www.twitch.tv/videos/744727931" rel="noopener noreferrer"&gt;this Twitch highlight&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Razor Pages Going
&lt;/h2&gt;

&lt;p&gt;Next up, I replaced the MVC project with a Razor Pages project. &lt;/p&gt;

&lt;p&gt;I had a few reasons for going this direction:&lt;/p&gt;

&lt;p&gt;1) Razor Pages is the "first class citizen" in ASP.Net Core world these days. MVC is 1000% still viable, etc., but I wanted to try the shiny new thing.&lt;br&gt;
2) The Razor Pages model (one page:one feature) makes good sense for an app like this one.&lt;br&gt;
3) I thought it'd be easier to deal with the DTO/ViewModel thing (I was mistaken, but only a little).&lt;/p&gt;

&lt;p&gt;Anyhoo, I got the project started, dropped in the Bootstrap 4 demo for an admin dashboard, and then I wrestled with getting Razor pages scaffolding to work for far too long on stream.&lt;/p&gt;

&lt;p&gt;Turned out it was a stupid bug on my part. See the vid above for details.&lt;/p&gt;

&lt;p&gt;Managed to get scaffolding working (very useful since I've never written with Razor Pages), then dove into what was finally clicking on DTOs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding DTOs to the Mix
&lt;/h2&gt;

&lt;p&gt;As I was dealing with getting my Razor Pages PageModel situated like I liked it, it finally hit me how DTOs should fit into my mix, at least.&lt;/p&gt;

&lt;p&gt;I definitely didn't want to pass and model bind the actual core entity object, of course. This opens you up to issues like overposting attacks, exposed data, etc. So I started building a ViewModel. &lt;/p&gt;

&lt;p&gt;While I was typing in the manual mapping code to go from entity to ViewModel, it finally occured to me that I shouldn't be doing that mapping in the UI layer itself: it should be &lt;strong&gt;mapped in the business logic layer&lt;/strong&gt;** to keep things DRY and the logic centralized.&lt;/p&gt;

&lt;p&gt;But I didn't want to pass a UI-level ViewModel to my service, so how do I...&lt;/p&gt;

&lt;p&gt;Oh. THAT's what a DTO is good for. 💡 🤦‍♂️&lt;/p&gt;

&lt;p&gt;That light bulb moment now shining brightly in my head, I added my first DTOs (&lt;code&gt;CreateCourseDto&lt;/code&gt; and &lt;code&gt;UpdateCourseDto&lt;/code&gt;), refactored my service methods (tests go red), fixed the tests (tests go green), and had a satisfied stretch break before moving back to the UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  First Working UI!
&lt;/h2&gt;

&lt;p&gt;DTOs and validation now in place and ready to rock, I moved back to the Razor Page now scaffolded and awaiting my updates. I replaced the direct entity and DbContext access with my DTOs and the &lt;code&gt;CourseService&lt;/code&gt; I've been building, fired it up, and lo and behold, it worked. Courses created.&lt;/p&gt;

&lt;p&gt;A very successful week indeed.&lt;/p&gt;

&lt;p&gt;Eventually. 🤣&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;These big decisions finally handled, I'm excited to pick up the pace and start really building things out.&lt;/p&gt;

&lt;p&gt;I found a great opensource Admin Dashboard template for Bootstrap 4 that I'm gonna work on next week, then start fleshing out the rest of our Course creation/editing/management processes.&lt;/p&gt;

&lt;p&gt;Until next time folks!&lt;/p&gt;

&lt;p&gt;- Fitzy&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Azure Function Templates with HTTP &amp; Storage Triggers, DI, and Options</title>
      <dc:creator>John "Fitzy" DeLancey</dc:creator>
      <pubDate>Thu, 03 Sep 2020 18:02:16 +0000</pubDate>
      <link>https://forem.com/fitzycodesthings/azure-function-templates-with-http-storage-triggers-di-and-options-4a4a</link>
      <guid>https://forem.com/fitzycodesthings/azure-function-templates-with-http-storage-triggers-di-and-options-4a4a</guid>
      <description>&lt;p&gt;Azure Functions scared me for a long time, but they shouldn't have. Getting started is VERY simple, especially with a little guidance on getting common features like dependency injection and the options pattern for configuration added.&lt;/p&gt;

&lt;p&gt;Let's take a look.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get the Git
&lt;/h2&gt;

&lt;p&gt;Check out &lt;a href="https://github.com/FitzyCodesThings/AzureFunctionTemplates"&gt;the project on Github&lt;/a&gt; or &lt;a href="https://dev.azure.com/FitzyCodesThings/AzureFunctionTemplates"&gt;get it on Azure DevOps&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch the Walkthrough
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/nBMO4-TWeBA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;For this "project," I really just wanted to:&lt;/p&gt;

&lt;p&gt;1) Solidify my grasp on how Azure Functions work&lt;br&gt;
2) Build a couple of templates I can use in future projects&lt;/p&gt;

&lt;p&gt;To that end, I created two different templates.&lt;/p&gt;

&lt;h4&gt;
  
  
  The first is an HTTP request-triggered Azure Function.
&lt;/h4&gt;

&lt;p&gt;Think of this type of function as an extremely simple RESTful API.&lt;/p&gt;

&lt;p&gt;You define a function name that gets translated to an endpoint like &lt;code&gt;http://localhost/api/MyFunction&lt;/code&gt; and can either send GET or POST requests to it, do some stuff, and return any standard response.&lt;/p&gt;

&lt;p&gt;The code for this is incredibly straightforward, though note that I didn't include DI &amp;amp; options in this template (check out the second function template for that).&lt;/p&gt;

&lt;p&gt;This kind of trigger would be fantastic for any kind of Zapier or IFTTT-style integrations and so much more.&lt;/p&gt;

&lt;h4&gt;
  
  
  The second template is an Azure Storage Queue-triggered Azure Function
&lt;/h4&gt;

&lt;p&gt;This type of function monitors a queue of messages built on the Azure Storage Queue feature.&lt;/p&gt;

&lt;p&gt;When a message is placed on the queue, the Function is looking for it, grabs it (and removes from the queue) and then does its thing.&lt;/p&gt;

&lt;p&gt;This is actually the first type of function I built, and I use it to kick off behind-the-scenes data exports so that my web application (and therefore the user who requested the export) aren't stuck waiting for a long-running web request to finish (or, more likely, fail because it takes longer than a reasonable timeout would allow).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is also the template that introduces dependency injection and the Options pattern for configuration.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Of particular importance is the customized &lt;code&gt;Startup&lt;/code&gt; class that you have to include to configure everything for DI/config. Take a look at the &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-3.1"&gt;Microsoft docs&lt;/a&gt; for more details on how all of that works.&lt;/p&gt;

&lt;p&gt;(And can I just say: holy crap how much have the MS docs improved over the years!?)&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started With the Templates
&lt;/h2&gt;

&lt;p&gt;Running the templates locally and even deploying them to Azure are verry straightforward.&lt;/p&gt;

&lt;p&gt;Rather than try to type it all out here, here are a couple of links to the "how to run it" parts of the video above.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/nBMO4-TWeBA?t=480"&gt;Running and testing the HTTP-triggered Function&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/nBMO4-TWeBA?t=1381"&gt;Running and testing the Queue-triggered Function&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Azure Functions (and serverless computing in general) just aren't as scary as I thought, and I'm seriously excited to start using them more and more in my development.&lt;/p&gt;

&lt;p&gt;If you have any questions (or feedback) about what I've built here, let me know! I'll do my best to help/incoporate suggestions.&lt;/p&gt;

&lt;p&gt;Otherwise, have fun going serverless!&lt;/p&gt;

&lt;p&gt;Until next time,&lt;br&gt;
- Fitzy&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>azure</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>CoreLMS: To DTO or Not to DTO, That is the Question (Among Other Thoughts)</title>
      <dc:creator>John "Fitzy" DeLancey</dc:creator>
      <pubDate>Thu, 20 Aug 2020 22:59:33 +0000</pubDate>
      <link>https://forem.com/fitzycodesthings/corelms-to-dto-or-not-to-dto-that-is-the-question-among-other-thoughts-54o0</link>
      <guid>https://forem.com/fitzycodesthings/corelms-to-dto-or-not-to-dto-that-is-the-question-among-other-thoughts-54o0</guid>
      <description>&lt;p&gt;REALLY wanted to get the &lt;code&gt;CourseService&lt;/code&gt; wrapped up this week, but ended up getting to one of those major decision points that will drive how things are done in the project from now on, and I didn't want to rush the decision.&lt;/p&gt;

&lt;p&gt;The choice now is: to use DTOs (data transfer objects) or not.&lt;/p&gt;

&lt;p&gt;I've never used them before, and I just can't get past the feeling that it ultimately amounts to a lot of code duplication (core entity + near-exact-copy DTO). &lt;/p&gt;

&lt;p&gt;I just don't know enough about the pattern (or how to do things efficiently/properly without it) yet.&lt;/p&gt;

&lt;p&gt;Also: new fun was had! I think I'll start every stream with a &lt;a href="https://www.codewars.com/" rel="noopener noreferrer"&gt;Codewars&lt;/a&gt; kata or two to warm up and fill in some syntax gaps I still have in ol' C#. Lots of fun.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get the Git
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/FitzyCodesThings" rel="noopener noreferrer"&gt;
        FitzyCodesThings
      &lt;/a&gt; / &lt;a href="https://github.com/FitzyCodesThings/core-lms" rel="noopener noreferrer"&gt;
        core-lms
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      An open source online learning management system project in ASP.Net Core MVC. Explores many best practices and patterns in modern software development.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Watch the Replay
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/o8avmr8ywMA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Skip to the Good Stuff
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Codewars Katas! &lt;a href="https://youtu.be/o8avmr8ywMA?t=126" rel="noopener noreferrer"&gt;00:02:06&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;List&amp;lt;Course&amp;gt;&lt;/code&gt; vs &lt;code&gt;IQueryable&amp;lt;Course&amp;gt;&lt;/code&gt; &lt;a href="https://youtu.be/o8avmr8ywMA?t=2520" rel="noopener noreferrer"&gt;00:42:00&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AddCourseAsync&lt;/code&gt; with TDD &lt;a href="https://youtu.be/o8avmr8ywMA?t=4620" rel="noopener noreferrer"&gt;01:17:00&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;To DTO or not to DTO? &lt;a href="https://youtu.be/o8avmr8ywMA?t=6099" rel="noopener noreferrer"&gt;01:41:39&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Project Update
&lt;/h2&gt;

&lt;p&gt;I did get a few things done (including figuring out why I like a certain way of using the "repositoryish" pattern over another).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Updated eager-loading &lt;code&gt;.Include()&lt;/code&gt;s on the Course entity (I'm used to lazy loading in EF and not having to think about it)&lt;/li&gt;
&lt;li&gt;Added &lt;code&gt;SaveChanges()&lt;/code&gt; and &lt;code&gt;SaveChangesAsync()&lt;/code&gt; overrides to handle soft deletes (with a caveat (see below)) and auto-filling &lt;code&gt;DateCreated&lt;/code&gt;, &lt;code&gt;DateUpdated&lt;/code&gt;, and &lt;code&gt;DateDeleted&lt;/code&gt; fields on &lt;code&gt;IAuditableEntity&lt;/code&gt;s&lt;/li&gt;
&lt;li&gt;Added the &lt;code&gt;AddCourseAsync&lt;/code&gt; method to &lt;code&gt;CourseService&lt;/code&gt; business logic (starting with the test, of course; really loving TDD as I get used to it)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Soft Deletes in Entity Framework Core
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Now: the caveat on soft deletes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Implementing softdeletes in EF Core is pretty simple on the surface.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use the new global query filter mechanism to filter soft-deletable objects with the &lt;code&gt;IsDeleted&lt;/code&gt; flag set to true (or a DateDeleted, etc.):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnModelCreating&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ModelBuilder&lt;/span&gt; &lt;span class="n"&gt;modelBuilder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;modelBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Student&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;HasQueryFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDeleted&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;modelBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;HasQueryFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDeleted&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Override &lt;code&gt;SaveChanges&lt;/code&gt; and &lt;code&gt;SaveChangesAsync&lt;/code&gt; to intercept any entities in the Deleted state and change them to modified with the IsDeleted flag set:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ChangeTracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Entries&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Only process soft-deletables (implements interface ISoftDeletable)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ISoftDeletable&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;IsAssignableFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetType&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;EntityState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Added&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CurrentValues&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"IsDeleted"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;EntityState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Deleted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EntityState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Modified&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CurrentValues&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"IsDeleted"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;SaveChangesAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seems simple enough, but I encountered an odd scenario if that's all you do to update deleted entities in an already-built project that I'm updating to .Net Core.&lt;/p&gt;

&lt;p&gt;The long and short of it is: if an entity you soft delete is contained in an &lt;code&gt;ICollection&lt;/code&gt; navigation property of a parent object (only scenario I've tested so far), the soft-deleted entry &lt;strong&gt;will not be removed from the parent collection&lt;/strong&gt; as long as you're using the same scoped instance of the DbContext (so during the same web request, in the same &lt;code&gt;using&lt;/code&gt; block, etc.).&lt;/p&gt;

&lt;p&gt;I've detailed the issue and linked a demonstration project in the &lt;a href="https://github.com/dotnet/efcore/issues/22103" rel="noopener noreferrer"&gt;GitHub issue here&lt;/a&gt;, but let me know if you've run into this and how you solved it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Data Transfer Objects (DTOs)
&lt;/h2&gt;

&lt;p&gt;Then, as mentioned in the intro, I got stuck on whether or not to use DTOs (then, if I do, whether I should add format and validation decorators on the DTOs or the core entities).&lt;/p&gt;

&lt;p&gt;I'm gonna put up another post in the next few days as I explore best practices for using DTOs (or not using them) and what makes sense for me.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Question: do you use DTOs? Why or why not? Any good articles/videos/courses I can check out that address it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Return &lt;code&gt;List&lt;/code&gt; or Return &lt;code&gt;IQueryable&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;Otherwise: I took a look at the &lt;code&gt;GetCoursesAsync&lt;/code&gt; method and considered whether to just return &lt;code&gt;List&amp;lt;Course&amp;gt;&lt;/code&gt; like I had been versus &lt;code&gt;IQueryable&amp;lt;Course&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;My argument for using &lt;code&gt;IQueryable&lt;/code&gt; was that it just made things simpler for implementing various where clauses, limits, etc. &lt;/p&gt;

&lt;p&gt;The problem became very apparent, though, when I realized that there's no &lt;code&gt;ToListAsync&lt;/code&gt; method on standard LINQ (it's an EF Core extension). This would mean I'd have to add an extra dependency on Entity Framework when I don't really want to (or give up Async operation, which I definitely don't want to do).&lt;/p&gt;

&lt;p&gt;There may be another solution to the problem that I didn't see, but for now, my plan is to look at using custom predicates to get the dynamic querying that I want without having to just return an &lt;code&gt;IQueryable&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Have I mentioned this is a learning project?&lt;/p&gt;

&lt;p&gt;And that it's mostly a learning project for ME? 🤣&lt;/p&gt;

&lt;p&gt;Pace WILL pick up soon, but these are big decisions, and I want to get this (as) right (as possible) from the beginning.&lt;/p&gt;

&lt;p&gt;Off to the Google I go to learn more about DTOs!&lt;/p&gt;

&lt;p&gt;Until next time!&lt;/p&gt;

&lt;p&gt;- John&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>webdev</category>
    </item>
    <item>
      <title>CoreLMS: Logging, Custom Exceptions, and more TDD</title>
      <dc:creator>John "Fitzy" DeLancey</dc:creator>
      <pubDate>Thu, 13 Aug 2020 19:20:27 +0000</pubDate>
      <link>https://forem.com/fitzycodesthings/corelms-logging-custom-exceptions-and-more-tdd-jpp</link>
      <guid>https://forem.com/fitzycodesthings/corelms-logging-custom-exceptions-and-more-tdd-jpp</guid>
      <description>&lt;p&gt;This week was a GREAT learning week for me. Got a lot more comfortable with the TDD mindset and got some good, solid infrastructure in place.&lt;/p&gt;

&lt;p&gt;Project feels like it's moving rather slowly for the moment (especially since I'm only working on it one day a week), but the pace will pick up quickly, especially as I continue getting comfortable with "the flow."&lt;/p&gt;

&lt;h2&gt;
  
  
  Get the Git
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/FitzyCodesThings"&gt;
        FitzyCodesThings
      &lt;/a&gt; / &lt;a href="https://github.com/FitzyCodesThings/core-lms"&gt;
        core-lms
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      An open source online learning management system project in ASP.Net Core MVC. Explores many best practices and patterns in modern software development.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Watch the Replay
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/nubSZ52fL_k"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Skip to the Good Stuff
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Configuring logging &lt;a href="https://youtu.be/nubSZ52fL_k?t=343"&gt;5:43&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Adding a custom exception &lt;a href="https://youtu.be/nubSZ52fL_k?t=1491"&gt;24:51&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;TDD/Next Services &lt;a href="https://youtu.be/nubSZ52fL_k?t=1847"&gt;30:47&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Project Update
&lt;/h2&gt;

&lt;p&gt;Made solid progress if not a LOT of it. I'm still getting my feet wet on implementing the TDD flow (and the unit tests themselves).&lt;/p&gt;

&lt;p&gt;Did have a great realization while working on this though.&lt;/p&gt;

&lt;p&gt;It was when I got to this state of the new &lt;code&gt;GetCourseAsync&lt;/code&gt; business logic method (which is covered by tests for context).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Course&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetCourseAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;course&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SelectCourseByIdAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;course&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogWarning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Course &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; not found."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ApplicationException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Course &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; not found."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;course&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Can you spot the problem?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's not actually a &lt;em&gt;problem&lt;/em&gt;, really, so much as it is a misapplication of ideas.&lt;/p&gt;

&lt;p&gt;I discovered the issue when I was trying to figure out how to log the actual exception that was (about to be) thrown. Obviously I can't do that, so what do I do?&lt;/p&gt;

&lt;p&gt;The light bulb began to go off when my good friend TheGrumpyGameDev in chat confirmed it for me:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I shouldn't need to log anything (or at least exception conditions) inside of business logic that's under unit testing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;(Not saying this is true 100% of the time, but it certainly applies in this case.)&lt;/p&gt;

&lt;p&gt;The logging in this instance should occur (IF REQUIRED) in whatever calling code catches the exception.&lt;/p&gt;

&lt;p&gt;In some situations, the exception may be perfectly acceptable, so why would I log a warning about that?&lt;/p&gt;

&lt;p&gt;I realize this (as so many things I write/do) seems very basic, but like I said: this project is about filling in gaps in my knowledge, and some of those are, well, pretty basic.&lt;/p&gt;

&lt;p&gt;In any case, the method code got simplified down to this well-covered simpler bit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Course&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetCourseAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;course&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SelectCourseByIdAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;course&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;               
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ApplicationException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Course &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; not found."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;course&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Easy-peasy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Looking forward to the pace picking up and getting through the basic infrastructure. I wanna see this thing in action! Probably won't be next week, but we'll get there soon.&lt;/p&gt;

&lt;p&gt;Until next time!&lt;/p&gt;

&lt;p&gt;- John&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>webdev</category>
      <category>tdd</category>
    </item>
    <item>
      <title>CoreLMS: Entities, Services, and TDD, Oh My!</title>
      <dc:creator>John "Fitzy" DeLancey</dc:creator>
      <pubDate>Fri, 07 Aug 2020 03:08:10 +0000</pubDate>
      <link>https://forem.com/fitzycodesthings/corelms-entities-services-and-tdd-oh-my-2dbd</link>
      <guid>https://forem.com/fitzycodesthings/corelms-entities-services-and-tdd-oh-my-2dbd</guid>
      <description>&lt;p&gt;If you want to build up your tolerance for looking like an idiot (everyone should), try implementing something you're just beginning to learn &lt;a href="https://twitch.tv/fitzycodesthings"&gt;live on Twitch&lt;/a&gt;....&lt;/p&gt;

&lt;p&gt;Oof.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get the Git
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/FitzyCodesThings"&gt;
        FitzyCodesThings
      &lt;/a&gt; / &lt;a href="https://github.com/FitzyCodesThings/core-lms"&gt;
        core-lms
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      An open source online learning management system project in ASP.Net Core MVC. Explores many best practices and patterns in modern software development.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Watch the Replay
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/CI-c2lR7bp8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Skip to the Good Stuff
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Start of code/adding entities &lt;a href="https://youtu.be/CI-c2lR7bp8?t=140"&gt;2:20&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Services and TDD &lt;a href="https://youtu.be/CI-c2lR7bp8?t=6646"&gt;1:50:46&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Project Update
&lt;/h2&gt;

&lt;p&gt;During yesterday's stream, I managed to flesh out several more of the entities I'll be using in the open source learning management system I'm developing live.&lt;/p&gt;

&lt;p&gt;We got:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Course&lt;/code&gt; entity fleshed out

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CourseLesson&lt;/code&gt; added

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CourseLessonAttachment&lt;/code&gt; added&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Person&lt;/code&gt; added&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Author&lt;/code&gt; added (which includes a &lt;code&gt;Person&lt;/code&gt; record, as well)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AuthorCourseLesson&lt;/code&gt; many-to-many entity added&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Then I embarrassed myself. Hard.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm still an absolute neophyte when it comes to TDD and unit testing in general.&lt;/p&gt;

&lt;p&gt;I knew that.&lt;/p&gt;

&lt;p&gt;So why did I think I'd just pop a service AND a test in live with no trouble?&lt;/p&gt;

&lt;p&gt;🤷‍♂️&lt;/p&gt;

&lt;p&gt;Anyhoo. Thank goodness for great community members and chatters. &lt;a href="https://www.twitch.tv/thegrumpygamedev"&gt;TheGrumpyGameDev&lt;/a&gt; (another great live code streamer) was there to rescue me and literally hold my hand through writing my first proper TDD test (on this project).&lt;/p&gt;

&lt;p&gt;First he stopped me from even creating the &lt;code&gt;ICourseService&lt;/code&gt; interface.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In TDD (the proper way), you START. WITH. THE. TEST.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;His question to me was, "How do you know what your interface should define?"&lt;/p&gt;

&lt;p&gt;The answer: your unit test TELLS you what functionality you should implement. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write the test&lt;/li&gt;
&lt;li&gt;See the test fail (even to compile at this stage)&lt;/li&gt;
&lt;li&gt;Write the code under test&lt;/li&gt;
&lt;li&gt;See the test pass&lt;/li&gt;
&lt;li&gt;Refactor/move on&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;And always in the smallest measures possible.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It's the Red-Green-Refactor pattern, but to a more minute level than I'd considered previously.&lt;/p&gt;

&lt;p&gt;So. We (I) fumbled and we (he) got me there.&lt;/p&gt;

&lt;p&gt;Here's the first TRULY properly arranged TDD test I've ever written.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Fact]
public async Task GetCoursesAsync_ShouldReturnExpectedCourseList()
{
    // given (arrange)
    List&amp;lt;Course&amp;gt; databaseCourses = new List&amp;lt;Course&amp;gt;();
    databaseCourses.Add(new Course()
    {
        Id = 1,
        Name = "Course #1"
    });

    databaseCourses.Add(new Course()
    {
        Id = 2,
        Name = "Course #2"
    });

    this.appDbContextMock.Setup(db =&amp;gt;
        db.SelectCoursesAsync())
            .ReturnsAsync(new List&amp;lt;Course&amp;gt;(databaseCourses)); 

    // when (act)
    List&amp;lt;Course&amp;gt; actualCourses = await subject.GetCoursesAsync();

    // then (assert)
    // 1. Actual list of courses == expected courses
    // 2. DB was hit once (and no more)
    actualCourses.Should().BeEquivalentTo(databaseCourses);
    appDbContextMock.Verify(db =&amp;gt; db.SelectCoursesAsync(), Times.Once);
    appDbContextMock.VerifyNoOtherCalls();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And here's the code it tested (written entirely AFTER the test was written and failing):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public async Task&amp;lt;List&amp;lt;Course&amp;gt;&amp;gt; GetCoursesAsync() =&amp;gt; await db.SelectCoursesAsync();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you're new to TDD or unit testing, that probably looks absurd.&lt;/p&gt;

&lt;p&gt;I mean seriously, WHY would you write 32 lines of code (including comments and new lines, but still) &lt;strong&gt;just to test&lt;/strong&gt; a SINGLE line of code?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: the service does call a repository method that just returns a simple dump of the Courses table, but I'm testing business logic, not practically built-in DB functionality&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Because now I NEVER, EVER have to worry about whether my &lt;code&gt;SelectCoursesAsync&lt;/code&gt; method is doing what it's supposed to do, no matter what I change in the system.&lt;/p&gt;

&lt;p&gt;It STILL seems like overkill. Why would that method ever change to need to be tested again?&lt;/p&gt;

&lt;p&gt;It probably won't. But it might. &lt;/p&gt;

&lt;p&gt;And as I add more and more and more simple, then more complex business logic to my application, I'll always be able to rely on the suite of tests I develop along the way to be sure I don't introduce a problem with unintended consequences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps in TDD
&lt;/h2&gt;

&lt;p&gt;All that said, I'm still scratching the surface in my description of TDD here and in my own understanding of it.&lt;/p&gt;

&lt;p&gt;To that end, I'm checking out two great resources recommended to me yesterday:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I've ordered &lt;a href="https://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530/"&gt;Test Driven Development: By Example&lt;/a&gt; by Kent Beck. Apparently the Bible of TDD.&lt;/li&gt;
&lt;li&gt;I'm gonna watch through the library of videos from &lt;a href="https://twitch.tv/jitterted"&gt;JitterTed&lt;/a&gt; on TDD (and also check out his upcoming course)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I've been sold on TDD (it's already saved my butt on another project). Now I learn.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;It was a frustrating but productive stream day for CoreLMS. Next week: more tests and services!&lt;/p&gt;

&lt;p&gt;Come hang out, chat, and save my butt, too. I need you. 🤣&lt;/p&gt;

&lt;p&gt;- John&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>webdev</category>
      <category>tdd</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Humility as Software Developers</title>
      <dc:creator>John "Fitzy" DeLancey</dc:creator>
      <pubDate>Fri, 07 Aug 2020 02:36:11 +0000</pubDate>
      <link>https://forem.com/fitzycodesthings/humility-as-software-developers-4p31</link>
      <guid>https://forem.com/fitzycodesthings/humility-as-software-developers-4p31</guid>
      <description>&lt;p&gt;I've been thinking about this a lot since a live stream that did NOT go according to plan yesterday.&lt;/p&gt;

&lt;p&gt;I wonder: is humility as big an issue for other software developers as it is for me?&lt;/p&gt;

&lt;p&gt;Had my butt handed to me trying to implement a new concept that I'm only vaguely familiar with while coding live yesterday, and it shook me to not only have to admit to myself but also face my (limited) audience with my deficiency. &lt;/p&gt;

&lt;p&gt;With the patient help of a great coder (and fellow live streamer) in the chat, I managed to get through it, but I was honestly prouder of overcoming my compulsion to run away from "the big scary thing," admit my weakness, and learn something.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So: do other devs out there have the same issue?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What happens when you get "called out" (directly or otherwise, even if you're just calling yourself out) on something you aren't proficient in?&lt;/p&gt;

&lt;p&gt;I think there are probably a number of factors to consider in my case at least. &lt;/p&gt;

&lt;h3&gt;
  
  
  We're told we're "so smart," usually from a very young age
&lt;/h3&gt;

&lt;p&gt;Whether it's our proficiency with technology, our ability to solve logical puzzles, or some other innate quality that leads us to this crazy profession, I feel like devs are often recognized for being "smart cookies." Whether that's TRUE, of course, is a different discussion.&lt;/p&gt;

&lt;p&gt;But in my case, then, when I confront something I DON'T know, I tend to recoil.&lt;/p&gt;

&lt;h3&gt;
  
  
  We're problem solvers
&lt;/h3&gt;

&lt;p&gt;Our job in code is to solve problems. We solve business problems with software solutions, we solve logical problems with elegant code, etc. &lt;/p&gt;

&lt;p&gt;When I face a problem I can't solve, then....&lt;/p&gt;

&lt;h3&gt;
  
  
  Maybe it's cultural
&lt;/h3&gt;

&lt;p&gt;Here I have the least understanding. For all I've been writing code for 15 years professionally and longer otherwise, I've been fairly insular (almost entirely solo dev work), so I don't have a good bead on the industry overall.&lt;/p&gt;

&lt;p&gt;Is "perceived weakness" something that's culturally frowned upon across the profession? &lt;/p&gt;

&lt;p&gt;Perhaps, coming from the opposite side, I've just gone in the other direction. Self-sufficiency (Stack Overflow doesn't count) is what puts food on my table.&lt;/p&gt;

&lt;h2&gt;
  
  
  Over to you
&lt;/h2&gt;

&lt;p&gt;How do you deal with humility in your day-to-day? &lt;/p&gt;

&lt;p&gt;I can certainly recommend live streaming if you think you can master your fight-or-flight instinct. I was forced to confront this thing live, and while it wasn't pretty, I managed it.&lt;/p&gt;

&lt;p&gt;Maybe there's a less painful way though? 🤣&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>mentalhealth</category>
    </item>
    <item>
      <title>CoreLMS: Specs and Project Organization</title>
      <dc:creator>John "Fitzy" DeLancey</dc:creator>
      <pubDate>Tue, 04 Aug 2020 20:29:39 +0000</pubDate>
      <link>https://forem.com/fitzycodesthings/corelms-specs-and-project-organization-3hmh</link>
      <guid>https://forem.com/fitzycodesthings/corelms-specs-and-project-organization-3hmh</guid>
      <description>&lt;p&gt;Let's get into the nitty-gritty.&lt;/p&gt;

&lt;p&gt;Last week I kicked the project off with some design notes, listed my goals, got the brand spankin' new solution scaffolded, and started the first entity for my open source learning management system built on an ASP.Net Core / EF Core stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get the Git
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/FitzyCodesThings"&gt;
        FitzyCodesThings
      &lt;/a&gt; / &lt;a href="https://github.com/FitzyCodesThings/core-lms"&gt;
        core-lms
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      An open source online learning management system project in ASP.Net Core MVC. Explores many best practices and patterns in modern software development.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Watch the Vid
&lt;/h2&gt;

&lt;p&gt;I'll detail the important bits below, but if you want to catch the whole (lightly edited) replay from the live stream, check it out here:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/KUHvtYaPeuE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Functionality Overview
&lt;/h2&gt;

&lt;p&gt;I covered my goals for this as a learning project in the first post of the series:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/fitzycodesthings" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K9fCAypx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--w7A_oxxt--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/443815/5bf9fe67-d531-4425-82d0-9b6550762264.png" alt="fitzycodesthings image"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/fitzycodesthings/corelms-let-s-build-a-cleanish-solidish-lms-from-scratch-in-asp-net-core-34hh" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;CoreLMS: Let's Build a Cleanish, SOLIDish LMS From Scratch in ASP.Net Core&lt;/h2&gt;
      &lt;h3&gt;John "Fitzy" DeLancey ・ Aug  4 ・ 2 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#dotnet&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#csharp&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#learning&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Here's a bare-minimum list of the "things this thing should do:"&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Support both on-demand (pre-recorded) and live online courses

&lt;ul&gt;
&lt;li&gt;Both simple (single video) and complex (modules/lessons) on-demand course formats&lt;/li&gt;
&lt;li&gt;Integration with Wistia for pre-recorded content
&lt;/li&gt;
&lt;li&gt;Support embedding third-party video players for live content&lt;/li&gt;
&lt;li&gt;Course progress tracking

&lt;ul&gt;
&lt;li&gt;Simple certificate issuance on completion&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;E-commerce functionality including:

&lt;ul&gt;
&lt;li&gt;Store front and course catalog&lt;/li&gt;
&lt;li&gt;Stripe integration for billing and payments&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Stretch:&lt;/em&gt; integration with Zapier, possibly specific marketing solutions&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Administrative interface for management of content, students, orders, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I Got Done This Week
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Scaffolded out the solution into the various "clean architecture"-style projects we'll be using:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Core&lt;/strong&gt; for all common interfaces, entity definitions, common types, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application&lt;/strong&gt; for internal business logic concerns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure&lt;/strong&gt; for external concerns (email services, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistence&lt;/strong&gt; for managing storage concerns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tests&lt;/strong&gt; for... I'll give ya three guesses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web.MVC&lt;/strong&gt; for the primary web-based UI&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Started the first entity (Course) &lt;/li&gt;
&lt;li&gt;Created first DB migration and tested the migration flow&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Didn't get a MASSIVE amount done on this first pass, but that's okay: thinking through things and organizing properly is &lt;em&gt;critical&lt;/em&gt; to project success (not that I don't expect to reorganize along the way, too).&lt;/p&gt;

&lt;p&gt;Next time, I'll be building out a few more basic entities, starting the first business logic service, and building the first unit test (in TDD fashion) for the project!&lt;/p&gt;

&lt;p&gt;Join me &lt;a href="https://twitch.tv/fitzycodesthings"&gt;live on Twitch&lt;/a&gt; on Wednesdays at 12pm Central / 5pm UTC to watch along and tell me how to fix things!&lt;/p&gt;

&lt;p&gt;Until next time,&lt;br&gt;
John / Fitzy&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>webdev</category>
      <category>csharp</category>
      <category>learning</category>
    </item>
    <item>
      <title>CoreLMS: Let's Build a Cleanish, SOLIDish LMS From Scratch in ASP.Net Core</title>
      <dc:creator>John "Fitzy" DeLancey</dc:creator>
      <pubDate>Tue, 04 Aug 2020 18:44:59 +0000</pubDate>
      <link>https://forem.com/fitzycodesthings/corelms-let-s-build-a-cleanish-solidish-lms-from-scratch-in-asp-net-core-34hh</link>
      <guid>https://forem.com/fitzycodesthings/corelms-let-s-build-a-cleanish-solidish-lms-from-scratch-in-asp-net-core-34hh</guid>
      <description>&lt;p&gt;(I love cheesy stock photos.)&lt;/p&gt;

&lt;p&gt;Woo! My first project to be detailed here on Dev (and built &lt;a href="https://twitch.tv/fitzycodesthings" rel="noopener noreferrer"&gt;live on Twitch&lt;/a&gt;, step by step).&lt;/p&gt;

&lt;p&gt;My primary client is a provider of continuing education, primarily online, for professionals, and our legacy PHP web app that acts as both Learning Management System and ecommerce platform is long, long overdue for a ground-up overhaul.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So let's build it!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Or part of it, at least. &lt;/p&gt;

&lt;h2&gt;
  
  
  Get the Git
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/FitzyCodesThings" rel="noopener noreferrer"&gt;
        FitzyCodesThings
      &lt;/a&gt; / &lt;a href="https://github.com/FitzyCodesThings/core-lms" rel="noopener noreferrer"&gt;
        core-lms
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      An open source online learning management system project in ASP.Net Core MVC. Explores many best practices and patterns in modern software development.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Project Overview
&lt;/h2&gt;

&lt;p&gt;My goal for this project is to build a functional, basic, and open source learning management system including basic e-commerce functionality.&lt;/p&gt;

&lt;p&gt;(I'll then take that core system and build on our more extensive customizations and business processes in closed source.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is a learning project for me.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My intent is to practice building according to a number of common patterns and best practices that I have less-than-ideal experience with (detailed below), so A) don't expect it to be perfect, and B) follow along and help me get it right!&lt;/p&gt;

&lt;h2&gt;
  
  
  Super High-Level Specs:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Build as a monolithic application (for now)

&lt;ul&gt;
&lt;li&gt;System design lends well to a microservices architecture for possible future exploration&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Basic Stack:

&lt;ul&gt;
&lt;li&gt;ASP.Net Core MVC (starting with 3.1, plan to move to 5.0)&lt;/li&gt;
&lt;li&gt;Entity Framework Core (ditto)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Build with base Bootstrap 4 (5?) to support easy theming in the future&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Learning/Demonstration Goals:
&lt;/h2&gt;

&lt;p&gt;I have a number of best practices and patterns that I want to implement (some for the first time) in this production-ready system.&lt;/p&gt;

&lt;p&gt;These include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SOLID adherence&lt;/li&gt;
&lt;li&gt;Clean Code Architecture&lt;/li&gt;
&lt;li&gt;Repository-ish Pattern with EF Core&lt;/li&gt;
&lt;li&gt;Unit and Integration Testing&lt;/li&gt;
&lt;li&gt;Proper logging (with Serilog?)&lt;/li&gt;
&lt;li&gt;CI/CD&lt;/li&gt;
&lt;li&gt;SPA for course access using Blazor (secondary goal)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Follow Along, Take Part!
&lt;/h2&gt;

&lt;p&gt;As mentioned at the top, I'll be developing this project live on Wednesdays on Twitch (and possibly other days as my schedule allows). I may occasionally wrap up boring bits off-stream, but all code will be published for open source use at the Github repo above.&lt;/p&gt;

&lt;p&gt;I'd be &lt;em&gt;honored&lt;/em&gt; for you to take part: join the conversation here or on Twitch, drop issues on Github, whatever you like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Since I already kicked off the planning and early development last week, I'll have another post up very shortly going over the thinking there and with a link to the archived broadcast.&lt;/p&gt;

&lt;p&gt;Other than that, I'll be &lt;a href="https://twitch.tv/fitzycodesthings" rel="noopener noreferrer"&gt;live tomorrow (Wednesday August 4) at 12pm CT / 5pm UTC&lt;/a&gt; to build a few more entities, start the first business logic service, and add the first unit tests (following TDD as best I can as I learn).&lt;/p&gt;

&lt;p&gt;Hope to see you around, and more than anything, I hope it helps ANYONE else get caught up or just learn a few things like I've been needing to!&lt;/p&gt;

&lt;p&gt;Cheers,&lt;br&gt;
John / Fitzy&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>webdev</category>
      <category>csharp</category>
      <category>learning</category>
    </item>
    <item>
      <title>db.Posts.FirstOrDefault(p =&gt; p.Title == "Hi, I'm Fitzy");</title>
      <dc:creator>John "Fitzy" DeLancey</dc:creator>
      <pubDate>Sun, 02 Aug 2020 19:47:27 +0000</pubDate>
      <link>https://forem.com/fitzycodesthings/db-posts-firstordefault-p-p-title-hi-i-m-fitzy-5ie</link>
      <guid>https://forem.com/fitzycodesthings/db-posts-firstordefault-p-p-title-hi-i-m-fitzy-5ie</guid>
      <description>&lt;p&gt;Hello!&lt;/p&gt;

&lt;p&gt;Uh. Now what?&lt;/p&gt;

&lt;p&gt;Okay, so my plan is to start sharing my journey in code here, and I figure I should begin with a "who is this guy" type of thing. So let's do that.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Basics
&lt;/h2&gt;

&lt;p&gt;I'm John/Fitzy. I've been writing code for 25 years (since I was 11), I've been doing it professionally for 15, and I've been self-employed full-time as a software developer/consultant for 10.&lt;/p&gt;

&lt;p&gt;I began building PHP web apps and have transitioned in the last 2-5 years to almost exclusively DotNet development with a sprinkling of Node.js and legacy PHP maintenance.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Journey
&lt;/h2&gt;

&lt;p&gt;Along my way, I've encountered plenty of roadblocks. Ethical choices, overbooking, getting in over my head, etc. I'm sure I'll discuss some of those here.&lt;/p&gt;

&lt;p&gt;The biggest hurdle I'm still leaping and the reason that led to this project of streaming / blogging / otherwise capturing my CURRENT journey is this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I stopped learning for nearly a decade.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Seem ridiculous? It is.&lt;/p&gt;

&lt;p&gt;I suspect it's also pretty common.&lt;/p&gt;

&lt;p&gt;It's very, very easy to get "stuck into your own code," particularly on long-running projects or client relationships (I've been working with my primary client for all of my 15 years, and my other main client for 5, on the same projects).&lt;/p&gt;

&lt;p&gt;It's then ALSO very easy to stop focusing on keeping up with the latest languages, frameworks, best practices, patterns/anti-patterns, etc.&lt;/p&gt;

&lt;p&gt;So while I was/am a "decent developer" (I love "world's okayest" as a mantra), and while my abilities to understand systems and logic were not affected and even grew, my ability to apply those basic skills diminished considerably.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Imagine trying to apply 15 year old basic PHP skills to a microservices architecture.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I've spent the last 2-3 years, then, beginning to "catch up." I think I'm making decent progress, but I've got a long way to go yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Plan
&lt;/h2&gt;

&lt;p&gt;My work centers around fintech applications and online learning systems, and I'm also seriously interested in blockchain technology (especially as it can be applied to those first two things).&lt;/p&gt;

&lt;p&gt;My goal is to share more of my journey as I learn to write better code to support my clients and my own projects, and I'm doing that on &lt;a href="https://twitch.tv/fitzycodesthings"&gt;Twitch&lt;/a&gt;, on Dev, and on a soon-to-be-relaunched personal site.&lt;/p&gt;

&lt;p&gt;Documenting my progress is a way for me to solidify it, and it is my sincere hope that by sharing it I can help other devs avoid the pitfalls I've jumped headlong into or encourage my fellow "stuck" devs to get "unstuck."&lt;/p&gt;

&lt;p&gt;Thanks for tolerating me along the way. &lt;/p&gt;

&lt;p&gt;To better code!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;John / Fitzy&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>writing</category>
      <category>career</category>
    </item>
  </channel>
</rss>
