Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: Don't use dynamic #303

Closed
onionhammer opened this issue Aug 12, 2016 · 42 comments
Closed

Feature request: Don't use dynamic #303

onionhammer opened this issue Aug 12, 2016 · 42 comments
Assignees
Labels
status: help wanted requesting help from the community status: work in progress Twilio or the community is in the process of implementing type: community enhancement feature request not on Twilio's roadmap

Comments

@onionhammer
Copy link

Dynamic defeats the purpose and removes any advantages of a statically typed language. There is no compile time error checking, and there is no way to explore the API with autocomplete, you just have to know sg.client.mail.send.post(requestBody), which is kind of crazy.

Also it relies on the DLR, which is much slower than normal compiled/jitted C# code.

@thinkingserious thinkingserious added type: community enhancement feature request not on Twilio's roadmap status: help wanted requesting help from the community labels Aug 12, 2016
@thinkingserious
Copy link
Contributor

Thanks @onionhammer!

Currently, our goal is to hide the implementation details through helpers. Here is our first try, but we have already received a ton of awesome feedback on how to improve: https://github.com/sendgrid/sendgrid-csharp/tree/master/SendGrid/SendGrid/Helpers/Mail).

Also, we want you to be able to pass in your desired HTTP client, this is why we removed it from the core of this library.

All that said, we've heard very compelling arguments ( thanks for adding another :) ) why we should ditch the reflection. So we will leave this ticket open and add it to our backlog. It can rise with additional +1s, comments or a pull request with a signed CLA.

@ryanelian
Copy link

ryanelian commented Aug 13, 2016

I agree with @onionhammer. It wasn't immediately clear that the email sender method is asynchronous due to the lack of Intellisense.

In addition, the library should be written using C# Coding Convention. (e.g. instead of .client.mail.send.post, should be .Client.Mail.Send.Post instead!)

Also, we want you to be able to pass in your desired HTTP client, this is why we removed it from the core of this library.

I rather have the library statically typed than sacrificing static typing for plug-ability.

But let's say we want to implement that feature, we can design it like this instead:

public interface IHttpClientMapper
{
    Task PostAsync(object parameter1, object parameter2, object parameter3);
}

// Allow developer to implement their own mapper using the interface defined above,
// then set a static property containing a HTTP mapper for use by all SendGridApiClient instances!
SendGridApiClient.HttpClientMapper = new MyHttpClientMapper()

This way, the library is extensible without sacrificing static typing.

add it to our backlog

IMHO this should be a high priority issue, not a backlog. But hey, I don't run the company. 😄

@thinkingserious
Copy link
Contributor

Hello @ryanelian,

Thanks for the feedback! I've added your vote to the issue.

With regards to the Async issue, we have: #200 (added your vote to that)

Intellisense should work once we get that integrated into the Mail Helper.

Regarding method naming conventions, we have: #239 (added your vote to that)

I believe we are using the proper naming conventions in the helper which will eventually hide the underlying HTTP client.

I like your suggestion for the IHttpClientMapper. We will revisit when it comes time to execute these changes.

It may be that we ditch the dependency to our dynamic client in favor of a static one.

Regarding the "backlog", I'm using that as a generic term to signify that it's something we will definitely execute as soon as we can. The priority is determined by a multitude of factors beyond what I described previously. I can say the priority on this is steadily rising and I'm looking forward to working on it again. We have a great deal of awesome feedback on this subject.

Thanks again!

@Corillian
Copy link

Corillian commented Aug 18, 2016

Please add my vote, I couldn't agree more that using dynamic makes the API clunky and unnecessarily difficult to use. There are so many levels of indirection within the client just to send an email and without intellisense you're forced to look at the source code to see what's going on. That's how I ended up here in the first place because I have no idea what the hell a response.StatusCode is, your documentation doesn't tell me, and now I have to dig through your code just to verify my suspicion that it's an integer status code from the web request since it could also be the .NET framework's strongly typed enumeration for HTTP status codes or something completely different. Pretty ridiculous.

Static typing is your friend and interfaces exist to hide implementations. I honestly can't think of a single good reason to use dynamic other than for consuming JSON objects, which is still dubious if the format of the JSON object never changes, as well as how ASP.NET uses it for ViewBag.

@saliehendricks
Copy link

+1

@Eirenarch
Copy link

I hope this release is some bad joke. Dynamic all the way? Conventions that go against the C# conventions (camelCase methods and properties)? It looks like someone let JS devs work on a C# library with no prior C# experience. Or maybe the library is autogenerated from swagger or something?

@thinkingserious
Copy link
Contributor

Thanks everyone for all the +1's!

This is now scheduled to be the next C# issue we'll tackle when I return on Monday, followed by enabling support for .NET Core (during that process we will look into providing binaries for 4.5.X and 4.6.X.)

Before we begin writing code for the rewrite, I will collect all the feedback from here and other threads and start a new thread (I'll ping all of you here on that thread) where I'll outline the new approach. If you have the time, your feedback will again be appreciated at that point.

We REALLY appreciate your patience and support on this. The constructive criticism we have received on this has been awesome.

Please note that our scheduling could change, depending on what new issues arise until then. In any case, this has become near the top of our backlog, so it will get done soon.

@Corillian,

In the new version, we will move to using the framework's enumeration. The dependency on the dynamic HTTP client will be removed.

@Eirenarch,

Yes, the majority of this library is auto-generated from our Swagger definition. It was a shortcut to allow the support for the v3 Web API endpoints across all our libraries as a MVP in a short timeframe. The plan was to listen, then iterate accordingly. We will continue to listen and iterate, so please keep the feedback coming :)

@Eirenarch
Copy link

Eirenarch commented Aug 18, 2016

Honestly giving us a swagger generated library is kind of insulting. We know how to call rest services. Either provide statically typed API that prevents errors and provides good developer experience by virtue of having proper types and methods or tell us to call your REST services directly.

@onionhammer
Copy link
Author

@Eirenarch I don't think this a very productive direction to take this issue discussion.

@thinkingserious Thanks for the good news - looking forward to your next updates

@thinkingserious
Copy link
Contributor

@Eirenarch,

That is the idea behind the helpers. What you are asking for is the same thing we wish to deliver, we just need some time to get there. Thanks again for helping validate and pushing us forward.

Also, I forgot to mention that we built the original code and automation tools ourselves so that once we do get it right we can scale across all our libraries. We did look at using existing Swagger auto-generating tools, but decided that in the end that would not serve our end goals.

@thinkingserious
Copy link
Contributor

Thanks for the kind words @onionhammer. I'm really excited about the next steps!

@saliehendricks
Copy link

Great to hear this is underway. Also very glad to hear about 4.5.0 libs
being supported. I just forked and compiled for 4.5 today and was annoyed
that I needed to do that for no apparent reason.

On 18 August 2016 at 22:05, Elmer Thomas notifications@github.com wrote:

Thanks for the kind words @onionhammer https://github.com/onionhammer.
I'm really excited about the next steps!


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
#303 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABvuwmKSJCNhHPdBIO9KuuBZMIvXhUbfks5qhLsHgaJpZM4JjMem
.

@thinkingserious
Copy link
Contributor

@saliehendricks ouch :(

We've heard that pain far too often, I can't wait to get that fixed too!

That said, we are planning to only officially support 4.5.2+ because those are the versions that Microsoft still supports.

May I ask why you are using 4.5.0? I'm asking to learn if we should indeed provide those dlls also. Thanks!

@saliehendricks
Copy link

saliehendricks commented Aug 18, 2016

We have a code base targeting 4.5.0 and a production environment upgrade to
4.5.2 would require site down time. Further to that we have been a bit lazy
about updating frameworks. Risk vs Reward and all that.

Based on the libraries code I can't really see the need for it to target
4.5.2 when 4.5 is completely sufficient and has wider reach with full
compat with 4.5+ and 4.6
+. I obviously have no idea about your plans going forward.

@thinkingserious
Copy link
Contributor

Great feedback @saliehendricks! I'll ping you when it comes time to implement this.

@thinkingserious
Copy link
Contributor

Hello everyone,

Just a quick update. It looks like I'll get back to this ticket a bit later in the week.

When I returned today, I found that several other issues bumped this one down a few notches.

I can't wait!

@thinkingserious
Copy link
Contributor

Hello Everyone,

I should not be making any time commitments :(

Our backlog is completely dynamic and while this issue is still in the top ten, it's not possible for me to give an exact day when this pops up next on the list.

I'm sending this update to let everyone know that will get done and it's high priority. I just can pin down the exact date.

Thanks for your continued patience.

That said, please feel welcome to start directing the conversation with additional feedback. We will work on this collaboratively.

@Jericho
Copy link

Jericho commented Aug 25, 2016

@thinkingserious Just want to remind you that several months ago I rewrote the entire SendGrid C# library and added the following features:

  • Everything is strongly typed (no dynamic types!)
  • HttpClient injected in constructor for easy unit testing and also allows web proxy to be configured
  • Sensible method names. For example, "Create" instead of "Post".
  • Fully 'async': all methods are awaitable
  • Avoid deadlocks in ASP.NET by making sure all async calls is configured with ConfigureAwait(false)
  • etc.

Unfortunately, my PR was closed without being merged. I'm guessing what I wrote didn't align with your "everything must be dynamic" architecture ;-) Since you seem to be reconsidering your architecture, feel free to take whatever you think is helpful from my branch.

@thinkingserious
Copy link
Contributor

@Jericho,

I'll be definitely pinging you when the time comes to implement. Thanks for following up!

@Eirenarch
Copy link

@Jericho I am also interested in hand-written statically typed library and honestly if SendGrid deprecate the current one that works with the v2 API (I think) I'd rather write my own. So I might be willing to help (but no commitment)

@JohnMcAvinue
Copy link

Completely agree about not using dynamic. I'm reverting to version 7 because 8 is simply too difficult to use and has been a regressive step in my opinion

@thinkingserious
Copy link
Contributor

Thanks for the vote @JohnMcAvinue!

@scottdock
Copy link

@thinkingserious Thank you so much for listening to the community and responding. We appreciate it! Will keep watching for the update!

@thinkingserious
Copy link
Contributor

Thank you for the positive support @scottdock! We appreciate it!

I've added your vote.

@brendonwm
Copy link

+1

@thinkingserious
Copy link
Contributor

I think the people on this thread are going to be key in next iteration of this library. If you have a moment, please check this out: #317

We are looking forward to working with you all to help make the next iteration of this library awesome.

@HeyJoel
Copy link

HeyJoel commented Sep 28, 2016

+1

@cyotek
Copy link

cyotek commented Oct 2, 2016

As you seem to have a voting system for priority, please consider my vote for going back to a statically typed API sooner rather than later. I've just upgraded one of my core projects to the latest version only to find the API completely different. Reworking that shouldn't be a problem, but the abhorrent nature of dynamic means firstly, I haven't a clue how to use the new API without digging through the docs (and oddly enough needing to read the docs to learn how to use a SMTP client of all things seems abnormal) and secondly because as I change the send mail implementation so infrequently, the next time I need to revisit it to add some new feature, I'll have forgotten how it works and will need to hunt it down all over again.

I'd also echo the comments about using "proper" .NET naming conventions, but at the end of the day, this is of less importance (to me) as long as the API is self documenting and will catch compile time syntax issues.

@thinkingserious
Copy link
Contributor

@cyotek,

Thanks for adding your voice! The detailed feedback is greatly appreciated.

It is definitely our intent to hide all of that low level implementation, we just have not quite gotten there yet on our roadmap. But thanks to great feedback like yours (and your added vote), we will get there sooner!

We hope that the Mail Helper will solve the issue you have identified about needing to dig through the docs to figure out basic functionality.

Along with removing dynamic dependencies, we will be enhancing the Mail Helper portion of the library shortly. You can check that project out here. Please let us know if you have any feedback on that as well :)

With Best Regards,

Elmer

@jason-persson
Copy link

Some quick feedback, after some internal discussion our company won't be updating to V3 API until a static API is provided for C#. So +1 from us.

@thinkingserious
Copy link
Contributor

Thanks @jason-persson,

Vote added.

@thinkingserious
Copy link
Contributor

Hello everyone,

To get this party started, we will begin here: #344

@thinkingserious thinkingserious self-assigned this Oct 13, 2016
@thinkingserious thinkingserious added the status: work in progress Twilio or the community is in the process of implementing label Oct 13, 2016
@thinkingserious
Copy link
Contributor

In this branch I'll be removing the dynamic functionality and merging into the v9beta branch when complete

I'm using the v9beta branch to group all the breaking changes described in these projects.

@abergs
Copy link

abergs commented Oct 16, 2016

YES, Have my Vote! This is the most confusing piece of .NET code I've ever used. I seriously think I might be better off just hand crafting the requests. Glad your actively working on this!! 👍

Would you say the new branch is kind of usable yet?

@Jericho How do I use your lib instead? Would you recommend using it?

@thinkingserious
Copy link
Contributor

Hi @abergs,

Thanks for your vote!

It's not quite ready and I would not recommend it for production as it's in flux right now.

You can follow along here and if you have any ideas, suggestions or feedback we would love to hear from you.

We are also implementing the other v3beta items here before releasing.

@Jericho
Copy link

Jericho commented Oct 19, 2016

@abergs I created a library based on the strongly typed code I wrote and I called it StrongGrid. Here's an example that demonstrates how to send emails using my library:

var from = new MailAddress("test@example.com", "John Smith");
var to1 = new MailAddress("recipient1@mailinator.com", "Recipient1");
var to2 = new MailAddress("recipient2@mailinator.com", "Recipient2");
var subject = "Hello World!";
var textContent = new MailContent("text/plain", "Hello world!");
var htmlContent = new MailContent("text/html", "<html><body>Hello <b><i>world!</i></b><br/><a href=\"http://microsoft.com\">Microsoft's web site</a></body></html>");
var personalizations = new[]
{
    new MailPersonalization
    {
        To = new[] { to1 },
        Subject = "Dear friend"
    },
    new MailPersonalization
    {
        To = new[] {to2 },
        Subject = "Dear customer"
    }
};
var mailSettings = new MailSettings
{
    Footer = new FooterSettings
    {
        Enabled = true,
        Html = "<p>This email was sent with the help of the <b>StrongGrid</b> library</p>",
        Text = "This email was sent with the help of the StrongGrid library"
    }
};
var trackingSettings = new TrackingSettings
{
    ClickTracking = new ClickTrackingSettings
    {
        EnabledInHtmlContent = true,
        EnabledInTextContent = true
    },
    OpenTracking = new OpenTrackingSettings { Enabled = true },
    GoogleAnalytics = new GoogleAnalyticsSettings { Enabled = false },
    SubscriptionTracking = new SubscriptionTrackingSettings { Enabled = false }
};
client.Mail.SendAsync(personalizations, subject, new[] { textContent, htmlContent }, from,
    mailSettings: mailSettings,
    trackingSettings: trackingSettings
).Wait();

My library also has convenient methods that simplify sending emails. Here's the simplified way to send a single email to a single recipient:

client.Mail.SendToSingleRecipientAsync(to, from, subject, htmlContent, textContent).Wait();

and here's the simplified way to send the same email to multiple recipients:

var recipients = new[] { to1, to2, to3 };
client.Mail.SendToMultipleRecipientsAsync(recipients, from, subject, htmlContent, textContent).Wait();

At the moment my library allows you to send emails and I am also in the process of releasing my code for all other resources in SendGrid's v3 API (e.g.: lists, contacts, subscription groups, api keys, templates, categories, etc.).

You can find my library on nuget and the code on GitHub.

@bbbford
Copy link

bbbford commented Oct 27, 2016

+1

@kirajhpang
Copy link

+1 for remove dynamic.

Recently my production is losing email via v2 due to unknown reason, maybe is related to DDos Attack last week.
So I do a urgent migrate from v2 endpoint to v3. Now, I able to send out my mails, but somehow on some cases I cannot be reproduce error email via sandbox, that's why I might need status code on response to give me more detail. Here come dynamic problem.

Looking forward for new release. Good Job guys!

@goalie7960
Copy link

👍

@thinkingserious
Copy link
Contributor

This fix (Remove Dynamic Dependency) has been merged into the v9beta branch: https://github.com/sendgrid/sendgrid-csharp/tree/v9beta

We are now moving to part 2 of 3 of this refactor: [v9beta] ASP.Net 4.5 to Core 1.0 Compatibility

Part 3 is: [v9beta] Mail Helper Enhancement (v3 mail/send)

Though I'm closing this issue, please free to continue the conversation here.

Thanks again for all the support and patience!

@isaacabraham
Copy link

Any plans for when this might be released? Currently the use of dynamic makes it difficult to use SendGrid from F#.

@thinkingserious
Copy link
Contributor

Hi @isaacabraham,

We are pushing to get the beta released to Nuget within the next few weeks.

In the mean time, @Jericho's StrongGrid is a great solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: help wanted requesting help from the community status: work in progress Twilio or the community is in the process of implementing type: community enhancement feature request not on Twilio's roadmap
Projects
None yet
Development

No branches or pull requests