Frontend & Cross-Platform UI
Desktop UI on Windows, macOS, and Linux. WPF when the target is Windows-only, Avalonia or Uno when it isn't. Same XAML I was writing before Microsoft had a designer for it.
Senior Software Engineer
24 years of .NET — UI, integrations, and the application layer between them. Industrial is where it got tested; enterprise is where it had to scale.
// About
The work itself looks about the same regardless of domain: desktop or cross-platform UI, C# services behind it, and the integrations that connect everything to whatever the business already runs on. A lot of mine has landed in industrial — historians, HMIs, DCS — because that's where the demands stack highest. The engineering travels.
Currently Senior Software Engineer at Capstone Technologies (a Voith company), developers of dataPARC — a process historian and real-time analytics platform used across pulp & paper, oil & gas, chemicals, and power generation. Previously CTO at B-Scada.
What I care about, in order: separation of concerns, code the next engineer can read without a tour guide, and UI that doesn't leak memory or drop frames after it's been running for a week.
// Expertise
Desktop UI on Windows, macOS, and Linux. WPF when the target is Windows-only, Avalonia or Uno when it isn't. Same XAML I was writing before Microsoft had a designer for it.
C# services, async pipelines pulling from multiple historians and enterprise systems at once, and the batching patterns that cut server load when clients ask for more data than the server expected. Not glamorous, but it's where most of the bugs live.
The connective tissue between the control room and everything upstream — historians, DCS, HMI, MES, ERP, lab/quality systems, auth, and whatever the vendor is calling their API this year. My daily work at Capstone Technologies on the dataPARC platform.
Builds, workflows, local tooling, and the dev environment that keeps everything else working. Boring on purpose.
What I end up doing when things get slow, grow too big, or start behaving in ways nobody intended. Architecture, SoC, TDD, memory leaks, weak references, event-graph cleanup, XAML conversions, and WebAssembly perf.
Lexer, parser, transformer, divisor, emitter. I've used this pipeline to convert seven industrial graphic formats — IOTA, DeltaV, PI, ProcessBook, PI Vision, WinCC, MOPS — into XAML that renders in WPF, Avalonia, and Uno.
The live-data layer that sits on top of historians and has to keep rendering while tags are still streaming in: dashboards, trends, KPIs, statistical process and quality control, smart alarms, predictive models and soft sensors, downtime tracking, batch analysis, and root-cause workflows. My day-to-day work at Capstone Technologies on the dataPARC platform.
The storage and query layer under the dashboards — how tag data is stored, compressed, queried, and aggregated at scale. Tag metadata, batch contexts, calculated tags, backfill, and the compression that keeps decades of one-second data still queryable.
// Selected work
Anonymized where it has to be. Concrete otherwise.
Current engineering work at Capstone Technologies (a Voith company) on the dataPARC platform — the real-time analytics and process historian layer used across pulp & paper, oil & gas, chemicals, and power. The work spans C# services, XAML UI, historian and enterprise-system integrations, and the visualization pieces that have to keep rendering while tags stream in. Ongoing.
IOTA, DeltaV, PI, ProcessBook, PI Vision, WinCC, and MOPS — seven vendor formats with seven different opinions about how a display should be structured, all parsed and emitted as XAML that renders in WPF, Avalonia, and Uno. This is where the pipeline on card 06 came from.
Client-side render paths refactored for measurable performance wins. Server load cut by batching calls that previously ran per-item. Architecture restored to actual separation of concerns — the kind of cleanup where the diff looks small and the runtime doesn't.
Ran the development team building industrial SCADA software. Made the architecture calls, set the review standards, and was the one the team called when something broke in production. Twenty-four years of .NET includes the stretch where I was responsible for the people shipping it too.
Back when WPF was still codenamed Avalon, the company I worked at shipped Aurora XAML Designer — the first dedicated XAML designer on the market. Microsoft's Blend came later. I've since shipped on XBAP, Silverlight, WPF, Uno, and Avalonia. Microsoft has deprecated most of the early list by now. The code mostly still runs.
// Engineering principles
The rules I follow — not generic "clean code" advice, the specific things I won't compromise on.
The code that ships is the rule. Style guides are the floor, not the ceiling.
TODO: implement, no sample-project scaffolding left in place.var when the right-hand side already names the type. Explicit types only when they clarify intent the expression doesn't.The profiler tells you where to look. It doesn't tell you what to do.
foreach doesn't.A string the compiler can't see is a refactor the compiler can't help with.
string.Empty over "". Two ways to say the same thing is one too many.nameof — over string-based coordination. The compiler catches what grep can't.Separation of concerns isn't a preference. It's what lets the rest of this list work.
The view is the least important layer. That's exactly why it gets the least logic.
ICommand for user actions. View-models expose intent; views wire it up.DataContext inheritance breaks down — which it will, in any non-trivial view.Lifetimes are the hard part of .NET. Treat them that way.
+= needs its matching -= on a lifecycle boundary — not "when convenient."IDisposable when the lifecycle is explicit; weak references when it can't be.Pipelines with explicit stages beat monolithic parsers every time the input shape changes — which it will.
lexer → parser → transformer → divisor → emitter. Each stage does one job and owes the next stage a clean contract.input.StartsWith("…") sprinkled across layers — that's what tokens exist for.Tests describe the contract. If they don't, they're just slow.
MiscTests.cs is an anti-pattern — it means nobody knows where the test should live.Tests suffix.Every dependency is a bet that the cost of maintaining it stays below the cost of writing it yourself.
// How I work
The stack is table stakes. This is the part behind it.
I'd rather spend three hours figuring out why something broke than ten minutes making it stop. Logs, runtime behavior, framework internals, reproduction in isolation — whatever gets to the actual cause.
Separation of concerns, responsibility boundaries, and thinking about who maintains this in three years. That person is usually me.
Allocation patterns, async behavior, rendering cost, startup time, WebAssembly limits — the things that quietly add up until someone files a ticket.
WPF, Uno, Avalonia, and the parts of XAML where bindings, dependency properties, gestures, and dynamic loading actually matter.
Getting UI, data, auth, APIs, add-ins, and vendor platforms to behave like one application. Most of the interesting bugs live between the boxes.
Smallest safe change most days. Full rewrite when the smallest change would be the fifth patch on the same broken pattern.
I pick up the things nobody else wants to touch and finish them. Work moves without being chased.
C#, XAML, WebAssembly, macOS services, build and dev infra. I don't need a specialist to make a decision in any of them. Currently poking at security tooling and local AI workflows for the same reason.
I can explain technical constraints to engineers, vendors, and non-technical stakeholders in ways all three can act on.
// Industries
Not greenfield demos.
Operational tooling where every minute of downtime has a dollar figure on it.
Process-heavy plants with historians, thousands of tags, and operator dashboards that can't afford to freeze.
Review cycles, compliance sign-offs, and the kind of scale that makes every decision expensive.
HMI and SCADA integrations, and the application layer sitting on top of them.
HMI and SCADA monitoring for nuclear operations — the kind of deployment where failure modes aren't theoretical.
Monitoring systems for rail and transit operations, including a subway deployment in South Korea. Uptime requirements that don't need explaining.
// Clients
Directly, through consulting, or via the platforms they run on.
// Contact
Consulting, code review, and small projects only — I already have a day job. If you're dealing with something hard in .NET, UI, or industrial integration — or something that used to work and doesn't anymore — send an email.
invokemethod@gmail.com