|
I have a requirement to write a console app which can perform migration operations from different versions of our software (an fairly complex enterprise horror), one after another to take us from 1.0 all the way to say 2.6 My thought to achieve this was: 1) a console app outside of our normal release schedule untied to any of our versioned dlls, which would use a class lib assembly also untied to any of our versioned dlls. 2) each release implements its own migration operations in a dll which would implement some interface from the class lib in 1) 3) the console app (or more accurately its class lib) would consume the migration operations dlls and call migrations in some order defined in some text format according to the customers version of our software. So we end up then with several migration operation dlls e.g. Which gives headaches with dll versioning. I believe I need to use AppDomains to separate them. 1.0 -> 1.1 migration operation dll which references MyCompany.Dothings.dll (version 1.0) 1.1 -> 1.2 migration operation dll which references MyCompany.Dothings.dll (version 1.1) I started looking into MAF to do this https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/bb384200(v=vs.100) However it seems like maybe support for this is not particularly active. Given the above is there a ideal way to do this? Does anyone have experiance with MAF? And am I even thinking along the right lines for this?
|
# ? Aug 13, 2019 12:36 |
|
|
# ? Jun 8, 2024 09:11 |
|
Dirty Frank posted:So we end up then with several migration operation dlls e.g. Which gives headaches with dll versioning. I believe I need to use AppDomains to separate them. I don't know about the rest but I'm pretty sure you don't need to separate them into different AppDomains. The documentation will tell you that you need to load an assembly "into an AppDomain" but to be very precise, it's not stating "into a unique AppDomain." I had to work on a project once where I was pretty sure they got that notion and it was its own kind of hell. The reason to have that separation is if: 1. The stuff you're loading risks being complete poo poo. 2. The hosting application has such a large uptime and the stuff your loading is small in comparison. Hence, you want to unload the stuff afterwards. If this is a separate application that's running the migration, and you don't have 3rd party developers involved, you should be able to load into the current AppDomain. To make life a little bit easier, you should have something in the interfaces that states the migration paths the code supports. I couldn't tell from what you were writing out if you were intending to infer that from the assemblies. At that point, the assembly version doesn't matter as much; X version 1.0 that migrates 1.0->1.1 vs Y version 1.1 doing 1.1->1.2 are apples and oranges and might as well have completely different names and versions.
|
# ? Aug 13, 2019 17:20 |
|
Rocko Bonaparte posted:I don't know about the rest but I'm pretty sure you don't need to separate them into different AppDomains. The documentation will tell you that you need to load an assembly "into an AppDomain" but to be very precise, it's not stating "into a unique AppDomain." I had to work on a project once where I was pretty sure they got that notion and it was its own kind of hell. The reason to have that separation is if: Couldn't you have type version conflicts if the migration DLLs aren't really carefully written or would segregated AppDomains not help with that?
|
# ? Aug 13, 2019 17:30 |
|
Munkeymon posted:Couldn't you have type version conflicts if the migration DLLs aren't really carefully written or would segregated AppDomains not help with that? Yes. (to both) It looks like there is a good, specific purpose for these assemblies. They are not participating in a distributed architecture where these things need to be popped in and out. So that should curb on the possible shenanigans, but it's amazing how innovative people can be when doing something stupid. The most common problem I remember was reusing the same name and version when trying a work-in-progress assembly in an environment that stayed resident between each load. I think that environment could have been more diligent about shedding the old assembly and reloading it. Regardless, that thing was using separate AppDomains and it did nothing to help there how it was written. Now, if the problem instead was that this was some distributed architecture that introduced APIs and stuff that could wander around the system, then Hoooly poo poo you should segregate that and also question your life decisions. The take I got of the problem was it was a plug-in system that got in, migrated some poo poo, and got out. Edit: and also I am assuming these imported assemblies are trusted. Rocko Bonaparte fucked around with this message at 19:41 on Aug 13, 2019 |
# ? Aug 13, 2019 19:38 |
|
Munkeymon posted:Couldn't you have type version conflicts if the migration DLLs aren't really carefully written or would segregated AppDomains not help with that? This is the problem I think AppDomains will help with. However! it seems AppDomains won't be present in .net Core at all and we will be porting to Core at some point in the future. So now the plan is to have a standalone migrator console app in each release (I mean in practice the code won't change much but they will be packaged separately in the release) which implements its own migration operations and some kind of Orchestrating app external to the release cycle which will call, not directly but as console apps, each versions migrator console app in order to go from start version to target version. Which I kind of like because I understand everything required. Seems like we're rolling a solution to a common problem though?
|
# ? Aug 13, 2019 19:54 |
|
Dirty Frank posted:This is the problem I think AppDomains will help with. However! it seems AppDomains won't be present in .net Core at all and we will be porting to Core at some point in the future. Did you happen to see in that what they intended to use instead of AppDomains? I've always seen some value in it to be able to upgrade and replace bits of code in a long-running application. Then again, it looks like the industry has switched over to commoditized cloud applications that can be taken up and down in bulk at-will. So upgrading generally just means shutting down the old instances and starting up the new ones. So maybe they're just decided to abandon the whole notion? Edit: Found it. quote:On .NET Core, the AppDomain implementation is limited by design and does not provide isolation, unloading, or security boundaries. For .NET Core, there is exactly one AppDomain. Isolation and unloading are provided through AssemblyLoadContext. Security boundaries should be provided by process boundaries and appropriate remoting techniques. So it looks like they're trying to apply some lessons learned or something. Rocko Bonaparte fucked around with this message at 22:32 on Aug 13, 2019 |
# ? Aug 13, 2019 21:07 |
|
My favorite feature of C# 8 - switch expressions. They read cleaner to me. For example:C# code:
Some WPF things that are different ...
|
# ? Aug 19, 2019 03:43 |
|
That’s some interesting syntax, took me a minute really digest what’s going on. Very cool.
|
# ? Aug 19, 2019 04:04 |
|
There is some interesting stuff. They added default implementations for an interface which I wouldn't have expected. The new switch is nice, it reads like pattern matching in F#. ^ and .. for array slicing is also cool. Maybe if we wait long enough C# and F# will just be the same language
|
# ? Aug 19, 2019 04:24 |
|
Xik posted:There is some interesting stuff. They added default implementations for an interface which I wouldn't have expected. One can dream...... They do copy a lot from it considering they always treat it like a redheaded stepchild. Mr Shiny Pants fucked around with this message at 06:05 on Aug 19, 2019 |
# ? Aug 19, 2019 06:02 |
|
Mr Shiny Pants posted:One can dream...... It's weird because quite a few CLR-level changes seem to be implemented to give F# support for things, and then years later C# gets implementations of those same features.
|
# ? Aug 19, 2019 06:28 |
|
I'd like Result<TResult, TError> and Option<T>/Maybe<T> types in the standard library tbh. F# has standardised these types in its ecosystem - it'd be nice if .NET could have standard ones so I don't need to think about rolling my own or choosing one of the many slightly- different equivalents in Nuget.
|
# ? Aug 19, 2019 06:40 |
|
These great features and more are waiting for you by just using F# - Call now for your introductory offer of Nobody Else Gets It Jesus Christ Why Cant We Use F# Around Here Come On Guys Its Not That Scary Wait What Are Those Pitchforks For
|
# ? Aug 19, 2019 07:02 |
Xik posted:There is some interesting stuff. Nice, they added What's the difference between an interface with default members and an abstract class with partial implementation?
|
|
# ? Aug 19, 2019 09:19 |
|
I guess the main difference would be that you can implement any number of interfaces but you can only derive from one abstract class. E: Also, the interface default members obviously can't access any class instance members, except through reflection (yuck).
SirViver fucked around with this message at 09:30 on Aug 19, 2019 |
# ? Aug 19, 2019 09:27 |
|
A big one is that classes don't inherit interface members (they implement them). That means to use a default implementation, you have to cast an instance of the class to the interface, similar to how you'd use explicitly implemented interface members.
|
# ? Aug 19, 2019 10:55 |
|
edit: nevermind
|
# ? Aug 19, 2019 13:53 |
|
LongSack posted:I’m less enthralled by the new using thing. Sure, it fixes the “problem” of mega-nested usings (my StringCypher class’ Encrypt and Decrypt methods have like 5 nested using blocks, so by the time you get to the innermost, like half of the screen is whitespace, but I’m not sure the new method is clearer. I think I’ll get used to it. Nesting usings is the one place I don't mind omitting braces+indenting for the scope(s) so it's kinda whatever
|
# ? Aug 19, 2019 14:27 |
|
Cuntpunch posted:These great features and more are waiting for you by just using F# - Call now for your introductory offer of Nobody Else Gets It Jesus Christ Why Cant We Use F# Around Here Come On Guys Its Not That Scary Wait What Are Those Pitchforks For What are some of the projects/scripts you've used F# for?
|
# ? Aug 19, 2019 16:04 |
|
Hughmoris posted:What are some of the projects/scripts you've used F# for? fscheck is real good
|
# ? Aug 19, 2019 17:58 |
|
Hughmoris posted:What are some of the projects/scripts you've used F# for? Figuring out F# is my boredom project of the year, so it's not like I have F# in production to refer back to. So far a lot of it has been 'ok take a problem I'd consider trivial to solve in C# and figure out how to think about it from a different direction and work it out functionally. My quip comes from experiences in trying to discuss how I've got this strong feeling there is really something super valuable there, and a lot of C# developers I know have the identical reaction of "But...why? I can do all of that faster and easier in C#!"
|
# ? Aug 19, 2019 20:32 |
|
I have a little ga ga goo goo baby C# question I've been going TypeScript for like 2 years now as an FED and I figure C# is a good sort of back-end language to actually pick up outside of the Node environment and I work in a .NET house so I guess its useful. I was passing an argument into a nested function inside a method and it got snotty about types. Fine, normal. The idea of the function is pretty simple: code:
code:
1. Why did it work? 2. Is this bad practice? 3. What is better practice?
|
# ? Aug 19, 2019 20:48 |
|
Why wouldn't it work? You can just use Object though.
|
# ? Aug 19, 2019 20:51 |
|
Ape Fist posted:I have a little ga ga goo goo baby C# question I've been going TypeScript for like 2 years now as an FED and I figure C# is a good sort of back-end language to actually pick up outside of the Node environment and I work in a .NET house so I guess its useful. 1. You stumbled across the syntax for generics in C#. Generally people will write this as code:
2. No.
|
# ? Aug 19, 2019 20:53 |
|
Cuntpunch posted:Figuring out F# is my boredom project of the year, so it's not like I have F# in production to refer back to. So far a lot of it has been 'ok take a problem I'd consider trivial to solve in C# and figure out how to think about it from a different direction and work it out functionally. I'm a novice hobbyist and struggle with designing OOP stuff so I was curious about trying my hand at FP. I've heard good things about F#.
|
# ? Aug 19, 2019 21:02 |
|
Ape Fist posted:... The only thing you did with the argument is call its method GetType(). GetType() is a method on object. Every non-static type inherits from object (either directly or indirectly), so that's OK to do regardless of the type of object. If you were doing something with your Any that required more of it than just being an object, you would have had to place constraints on it or the compiler wouldn't have allowed it. But as someone else said, you could have instead declared the parameter to be of type object and that would arguably be better style since what you're using is the fact that the parameter is of type object; you're not really using the "genericness" of the method.
|
# ? Aug 19, 2019 21:44 |
|
Hammerite posted:The only thing you did with the argument is call its method GetType(). GetType() is a method on object. Every non-static type inherits from object (either directly or indirectly), so that's OK to do regardless of the type of object. If you were doing something with your Any that required more of it than just being an object, you would have had to place constraints on it or the compiler wouldn't have allowed it. A general guideline which may be useful for someone coming from untyped/weakly-typed languages: If you're passing around things as object and casting them, or if you're doing a lot of if (someObject is SomeType), you almost certainly have a design problem.
|
# ? Aug 19, 2019 22:44 |
|
Hughmoris posted:What are some of the projects/scripts you've used F# for? We have a few internal sites that use Suave for F# web hosting, and the majority of the publishing process of Xamarin uses is in F#, which includes the tools/scripts used to insert our products into VS and VS For Mac.
|
# ? Aug 19, 2019 23:19 |
|
Hughmoris posted:I'm a novice hobbyist and struggle with designing OOP stuff so I was curious about trying my hand at FP. I've heard good things about F#. I think F# is a nice sweet spot for functional stuff. Haskell may be more pure and academic, but it's also in its little world. Clojure is cute and has interop with a major OO ecosystem, but the last time I looked at it, I found the tooling wanting - and the Lisp 'look' to be more difficult to follow. I'd be curious what pain points you're feeling around OOP design, though - I've heard FP described as a very pure version of applied OOP.
|
# ? Aug 19, 2019 23:20 |
|
F# is great because you can ease your way into functional programming with it. You can treat it as weird C# and start refactoring code as you start to think about better ways to rewrite to make it smaller and more functional, as it were. Getting hung up on the “functional” part (and being told by functional programming-heads how you’re doing it wrong et all) by going all in is tough, but you can ease your way into it.
|
# ? Aug 19, 2019 23:25 |
|
Hughmoris posted:What are some of the projects/scripts you've used F# for? I have found production F# in a C# shop useful in two places:
FsCheck is indeed great, but you're not going to be able to get a team to learn an entirely new language just to write tests, especially because FsCheck requires you to use one of the most alien features in the language. There may be more uses of F# that work, these are just the ones I'm aware of. For typical boring line-of-business applications, F# has the weakness that there is no standard project organization the way there is with C#, so you have to spend a little time explicitly deciding on one. If your entire team is already fluent in F# this might be worth it (people who like F# tend to be more productive in it than, say, C#) but I haven't yet found a business case when there's a learning curve that matters. e: also the tooling is always a few steps behind
|
# ? Aug 20, 2019 00:56 |
|
How do you all handle string literals? For strings that appear more than say 2 or 3 times, I have a Constants class (which also has ‘numbers’ like exit codes, etc.), but for strings that are one-offs, I just code them inline. Obviously my apps are not internationalized. I recently installed a Microsoft code analyzer (and quickly uninstalled it) which bitched at literally every string literal saying it should be from a resource dictionary instead. So what do you all do?
|
# ? Aug 20, 2019 05:09 |
|
raminasi posted:FsCheck is indeed great, but you're not going to be able to get a team to learn an entirely new language just to write tests, especially because FsCheck requires you to use one of the most alien features in the language. The joy here for me is that since it's all CLR, you can use FsCheck in your C# unit tests just as easily.
|
# ? Aug 20, 2019 08:48 |
|
LongSack posted:How do you all handle string literals? For strings that appear more than say 2 or 3 times, I have a Constants class (which also has ‘numbers’ like exit codes, etc.), but for strings that are one-offs, I just code them inline. Obviously my apps are not internationalized. I recently installed a Microsoft code analyzer (and quickly uninstalled it) which bitched at literally every string literal saying it should be from a resource dictionary instead. I have sometimes done this Constants class thing you describe, but it's usually for things that are internal and not user-facing, e.g. the names of config setting keys, default values for configuration settings, and such. I'm not sure I'd store messages for the user that way, even if the app isn't internationalised and the strings are all in English I might keep them closer to the point of use - or in any case, separate from the more "techy" constants. e: when I've done this it has been in ASP.NET projects. It's convenient to be able to write using static MyProduct.MyProject.Constants; at the top of Startup.cs. Hammerite fucked around with this message at 09:53 on Aug 20, 2019 |
# ? Aug 20, 2019 09:51 |
|
I mean, why not just use resources like the analyser suggests? It's easy enough to set up, and once you've done it the usage is basically identical to your constants class anyway.
|
# ? Aug 20, 2019 10:50 |
|
Jabor posted:I mean, why not just use resources like the analyser suggests? It's easy enough to set up, and once you've done it the usage is basically identical to your constants class anyway. I would like to preface this by saying that I don't want to appear emotionally invested in doing things the way I described in my post, so please don't interpret this that way. Your suggestion is devoid of reasons to do as you suggest. You say that it's "easy enough to set up" - OK, but that's not a reason to do as you say, it's merely the absence of one specific reason not to. It isn't, on its own, a basis for choosing a course of action. And the alternative you're contrasting it with (creating a constants class) is at least equally easy; easier if you haven't set up a resource dictionary before, because it doesn't come with the overhead of having to figure out how to do that (whereas I already know how to type stuff into a file of C# source). In addition, there is a heuristic that applies to suggestions that run along the lines of "why not do things using (piece of machinery that's part of the framework)?" which is "does it seem like the kind of thing that will at some point become 'the old way' of doing things?" Maybe resource dictionaries have been around since .NET 1.0 and are unlikely to ever change, or maybe they were added last week and will change at the drop of a hat, I don't know. But there are aspects of .NET these days that change rapidly (particularly in the area of ASP.NET Core), and if something smells like a thing that will become obsolete at some point, that's a basis for being wary of it. To me, as someone who doesn't know what a resource dictionary is or how stable a feature it is, your suggestion has that smell. e: I would follow this up by acknowledging that the considerations I outline in the previous paragraph are very weak reasons for choosing a course of action, and might be easily overturned by somebody posting a list of reasons why resource dictionaries are actually really good and worth using. However, weak as they are, they are still more than the zero reasons you provided. Hammerite fucked around with this message at 11:18 on Aug 20, 2019 |
# ? Aug 20, 2019 11:13 |
|
I mean, the baseline evidence in favour is that "Microsoft's code analyzer is recommending them", which certainly suggests that they're the generally recommended way to handle UI strings - or at least worthy enough to look into rather than uninstalling the analyzer in a huff.
|
# ? Aug 20, 2019 12:26 |
|
Also it’s not hard to suppress a particular diagnostic ID if you’re not interested in it.
|
# ? Aug 20, 2019 17:08 |
|
Jabor posted:I mean, the baseline evidence in favour is that "Microsoft's code analyzer is recommending them", which certainly suggests that they're the generally recommended way to handle UI strings - or at least worthy enough to look into rather than uninstalling the analyzer in a huff. Not a huff, so much, more a realization that i'm 30,000 lines of code into this app, that's 1/3 to 1/2 done, and there's no way i'm going to refactor every single string into some resource dictionary lookup. Maybe next project.
|
# ? Aug 20, 2019 17:13 |
|
|
# ? Jun 8, 2024 09:11 |
|
Thinking more about this, how does it work? If we’re talking about a literal ResourceDictionary, then each string needs a key which is, itself, a string. So is fxcop gonna bitch at me about using string literals as key values? And what do you use as key values? Either a key that’s descriptive enough that someone reading the code has an idea what the string is, or else something like ”MSG0000001” in which case whoever is reading the code needs to keep the dictionary up in another monitor to see the messages. Obviously, I’ve never done this before, so I could be missing something blindingly obvious (wouldn’t be the first time; won’t be the last), but it seems like I’m replacing one set of strings (values) with another (keys), and short of localization, I don’t see an advantage.
|
# ? Aug 21, 2019 05:09 |