This blog has relocated to

Monday, October 31, 2011

My Thoughts on MEF

Ever since MEF was conceived, despite the authors saying that it is not an IoC container, it has since evolved to become one of the more popular IoC containers.  I’ve always avoided it because I disagree with using attributes, and I’ve had no reason to use it over Autofac or Windsor.

Recently, I found a reason to use it – Metro-style applications only support MEF so far.  My Twitter client ping.pong uses Autofac as the IoC container.  It uses some very basic functionality like factories and hooks.  To my surprise, MEF has no support for either of these.

Coming across these limitations solidifies my opinion that MEF is a plugin container, not an IoC container.

First let’s take a look at automated factories. What I mean is that by registering Foo, like so:


the container will automatically provide us a Func<Foo> without explicitly having to register it. This can be useful when you want to create an instance of Foo some time in the future rather than at constructor time.  You can do this with MEF via an ExportFactory<T>, but it’s limited because you cannot override dependencies at resolve time.

For example, let’s say Foo has a constructor of Foo(Bar1, Bar2, Bar3). With MEF, you have no control at resolution time what the Bars are. A container that has support for automated factories (like Autofac and Castle Windsor), will let you resolve a Func<Bar1, Foo>, which lets you override Bar1 at resolve time. Similarly, you can resolve a Func<Bar1, Bar2, Bar3, Foo> and override all dependencies. Any dependencies not overridden fall back to their configuration in the bootstrapper. This is a very useful feature, and coupled with the scoping features for automatic disposal it opens up many doors for elegant solutions for what otherwise are complicated problems.

On to the second point; MEF has limited extension points. This one sounds odd since MEF is all about designing decoupled plugins so surely it should have extension points! The problem here is that MEF is designed as an explicit API (attributes are required) rather than an implicit API. In Autofac, you can scan an assembly and register every type. In MEF, every class needs to have an [Export] on it.  It also baffles my mind why [ImportingConstructor] is required even when there’s only one constructor. All this explicitness means you lose a bunch of “free” extension points that typical IoC containers have, like this:

  .OnActivated(x => x.Context.Resolve<IEventAggregator>().Subscribe(x.Instance));

What the code above is saying that every time any component is activated, it will subscribe to the event aggregator. If the component doesn’t IHandle<> any messages, it’s a no-op and continues on. If the instance does IHandle<> messages, this will ensure it’s hooked up.

The closest thing I could find in MEF was IPartImportsSatisfiedNotification (yes, an interface, more explicitness!).  It contains a single method OnImportsSatisfied() which gets called when the part is created.  Needless to say, the one line of code from Autofac would translate into a method for every implementation of IHandle<>, and since OnImportsSatisfied() contains no contextual information, every component will need IEventAggregator injected just to be able to call Subscribe.

To fully complete this example, Autofac has the following methods when registering a component: OnRegistered, OnPreparing, OnActivating, OnActivated, and OnRelease.  Each of these methods gives you complete contextual information at the time it is called like access to the current scope of the container, the instance (if applicable), which component which requested the dependency, etc.  This makes it almost too easy to extend the container.

For MEF, the only real extension point is an ExportProvider.  It is pretty low level (all it does is parse attributes for you) so to write anything similar for MEF requires a lot more code.  To further illustrate this point, compare the interception modules from AutofacContrib and MefContrib.  The Autofac implementation is a single file with a couple extension methods.  The MEF implementation is an entire namespace, over multiple classes, not the mention that it also relies on other infrastructure code in MefContrib.  Basically, the guys that wrote MefContrib had to write a mini-container within MEF.

MEF is great for building extremely loosely coupled applications.  I don’t think it has any business in an application where you know and own all of the dependencies; there are simply better libraries for that.

Sunday, October 9, 2011

ping.pong Twitter Client

I have a whole series dedicated to blogging about how I wrote a Twitter client from scratch, but if I want anyone to actually use it, I better do some advertising :-D.

ping.pong is a fast and lightweight Twitter client written in Silverlight.  As of this moment it targets v4 but will likely target v5 whenever that is released.

Here are some highlights…

Visually Pleasing


The UI is based on your typical column-based design.  The column widths will automatically resize to take up all available horizontal space.  There is no horizontal scrolling.

Access to the Streaming API

No more rate limits!  Your timeline is connected directly with Twitter’s streaming API, which means whenever someone you follow tweets you will know about it in almost near real-time.  Searching is also done through the streaming API.

Fast & Lightweight

ping.pong was built to run fast with low CPU utilization.  Even when stream searching for “e” (yes, the letter E), the CPU usage stays under 15%.  The maximum number of tweets that Twitter sends appears to be 50 per second.


ping.pong will quickly show an entire tweet conversation by navigating reply tags back to the original tweet that started it all.

Free & Open Source

The full source code for ping.pong can be found on GitHub.  You can compile it, make modifications as you please, and run it yourself.  The only thing missing is the consumer keys which uniquely identifies this client from another.  You can generate them through Twitter once you have a developer account.


The latest and greatest can be quickly installed from here.  Check back periodically for updates!

Thursday, September 29, 2011

Push Driven Development with Reactive Extensions

This is going to be the last post that concludes my series on building a real-time push app with Silverlight.  Any additional posts would likely be outside the context of writing a push app and more about how I’m adding features to ping.pong, my Twitter app, so I think this is a good place to wrap up and talk generally from a top down overview of building a push-style application.

Here’s a recap of everything discussed so far:

Part 1:  Basics – Creating an Observable around a basic HTTP web stream against Twitter’s streaming API

Part 2:  Subscription and Observation of Observables

Part 3:  Basics of UX design with a look at shadows and gradients.

Part 4:  Integrating with 3rd party libraries, notably Caliburn Micro and Linq2Twitter and how to achieve polling with observables.

Part 5:  A minor hick up with Linq2Twitter.

Part 6:  Taking advantage of transparencies to improve the design and reusability of UX.

Part 7:  A summary of all things encountered so far, replacing Linq2Twitter with Hammock, first release of code to GitHub, and a binary released capable pulling and streaming tweets from Twitter.

Part 8:  Examples of using Caliburn Micro to easily resolve data bindings that otherwise would be much more effort.

And that leads us to this post…

PDD (Push Driven Development)

One of the main goals of this series is to create a performant Silverlight app based on push principles, as opposed to more traditional pull principles.  To that effect, ping.pong has performed remarkably well and is limited only by Twitter’s throttling, which currently appears to be maximum of 50 tweets per second via the streaming API.

Writing the application from a push-driven mindset was definitely unintuitive at first, and I had to refactor (actually rewrite is more accurate) the code many times to move closer to a world where the application is simply reacting to events thrown at it (as opposed to asking the world for events).

To be absolutely clear on what I mean on the differences between push and pull, here’s a comparison:

Pulling Push
var e = tweets.GetEnumerator();
while (e.MoveNext()) // is there more?
  e.Current; // get current
IObservable<Data> data = /* get source */

// whenever data comes, do something

On the pulling side, the caller is much more concerned with the logic on how to process each message.  It needs to repeatedly ask the world, “hey, is there more data?”.

On the push side, the caller merely asks the world, “hey, give me data when you get some”.

Twitter is a perfect example because their APIs have both a pulling and pushing models.  Traditional clients poll continuously all the time, and many had configurable options to try to stay under the 200 API calls per hour limit.  Most of Twitter’s API still consists of pulling, but the user’s home line and searching can be streamed in near real time via the streaming API, aka. push.  Streaming tweets effectively removes the API call limit.

Push and Pull with Reactive Extensions

The beauty of Rx is that regardless of whether it is actually pushing or pulling, the API will look same:

IObservable<Tweet> tweets = _client.GetHomeTimeline();
tweets.Subscribe(t => { /* do something with the tweet */ });

As far as the caller is concerned, it doesn’t care (or needs to know) whether the GetHomeTimeline method is polling Twitter or streaming from Twitter.  All it needs to know is when a tweet comes it will react and do something in the Subscribe action.

In fact, Subscribe simply means “when you have data, call this”, but that could also be immediately, which would be analogous to IEnumerable.

However, if that was the only thing Rx provided it wouldn’t be as popular as it is, because other pub/sub solutions like the EventAggregator already provide a viable asynchronous solution.

Unlocking Rx’s power comes with its multitude of operators.  Here’s an example:

public static IObservable<Tweet> GetStreamingStatuses(this TwitterClient client)
  return client.GetHomeTimeline()

GetHomeTimeline and GetMentions initiate once-only pull style API calls, while GetStreamingHomeline will initiate a sticky connection and stream subsequent tweets down the pipe.

The Merge operator is defined as this: “Merges an observable sequence of observable sequences into an observable sequence.”

I think a better description would be “whenever there is data from any of the sources, push it through”.  In the example above, this would translate to whenever a tweet comes from either the home timeline or the mentions timeline, give me a Tweet (first-come-first-push), followed by anything from the streaming timeline.

And there lies one of the greatest beauties of Rx.  All of the complexity lies solely on setting up the stream and operators.  And that, also, is its disadvantage.

Rx Complexity

Let’s take a look at the Concat operator, defined as: “Concatenates two observable sequences.”  In the remarks sections it states this: “The Concat operator runs the first sequence to completion. Then, the second sequence is run to completion effectively concatenating the second sequence to the end of the first sequence.”

Let’s try it out:

var a = Observable.Interval(TimeSpan.FromSeconds(1)).Select(x => x.ToString());
var b = Observable.Interval(TimeSpan.FromSeconds(1)).Select(x => "s" + x);
// output: 0, 1, 2, 3, 4...

As expected, only numbers are printed because the first sequence never ends, so it won’t concatenate the second one.  Let’s modify it so that it does finish:

int count = 0;
var a = Observable.Interval(TimeSpan.FromSeconds(1))
    .TakeWhile(_ => ++count < 5)
    .Select(x => x.ToString());

Note, that using Observable.Generate is preferred because it doesn’t introduce an external variable, but I stuck with Interval so the code looks similar to the second observable.  As expected again, it will print “0, 1, 2, s0, s1, s2”.

OK, let’s spice things up.  Let’s make b a ConnectableObservable by using the Publish operator, and immediately call Connect.

int count = 0;
var a = Observable.Interval(TimeSpan.FromSeconds(1))
    .TakeWhile(_ => ++count < 5)
    .Select(x => x.ToString());
var b = Observable.Interval(TimeSpan.FromSeconds(1)).Select(_ => "s" + _).Publish();

What do you think the output of this will be?  The answer is “0, 1, 2, 3, s5, s6, s7, …”

Despite using the same Concat operator, the result can be very different depending on the source observables.  If you use the Replay operator, it would have printed “0, 1, 2, 3, s0, s1, s2, …”

Years and years of working in synchronous programming models have trained us to think in synchronous ways, and I picked Concat specifically because Concat also exists in the enumerable world.  Observable sequences are asynchronous, so we never know exactly when data comes at us, only what to do when it does.  And because streams occur at different times, when you combine them together there are many many ways of doing so (CombineLatest, Merge, Zip, are just a few).

The greatest hurdle to working in Rx is to know what the different combinations do.  This takes time and practice.  RxTools is a great learning tool to test out what all the operators do.

Unit Testing

Last but not least, Rx can make it easier to write unit tests.  The concept is easy: take some inputs and test the output.  In practice this is complicated because applications typically carry a lot of state with them.  Even with dependency injection and mocking frameworks I’ve seen a lot of code where for every assert there is 10 lines of mock setup code.

So how does it make it easier to test?  It reduces what you need to test to a single method, Subscribe, which takes one input, an IObservable<T>.


Rx is a library unlike any other you will use.  With other libraries, you will add them to your solution, use a method here or there, and go on with your life.  With Rx, it will radically change the way you code and think in general.  It’s awesome.

Wednesday, September 21, 2011

Building a Real-time Push App with Silverlight: Part 8


Exploring Caliburn Micro

As I hinted in earlier posts, Caliburn Micro has some wicked conventions that makes for writing MVVM super easy, and it also have a very convenient syntax for hooking up events.  For example, the following:

<Button Content="R">
       <i:EventTrigger EventName="Click">
           <i:InvokeCommandAction Command="{Binding ReplyCommand}" CommandParameter="{Binding}" />

Can be rewritten like this:

<Button Content="R" cal:Message.Attach="[Reply($dataContext)]" />

There are some smarts going on here.  Caliburn Micro will default to the Click event for buttons.  For a full syntax, it would be cal:Message.Attach=”[Event Click] = [Reply($dataContext)]”.  As you can imagine, that will call the Reply method and pass in the current data context.  You can also pass in other things like $this, $source, or $executionContext for full access to anything and everything Caliburn Micro itself has access to.

The coolest thing about this is it gives you some wicked control over how your data context gets set.  Ever struggled with popup windows or data grids and using weird hacks to get the binding correct?  Caliburn Micro makes this very easy.  Here’s an example.

  1. I have a DataTemplate which renders the UI for the model Tweet.
  2. Tweet is just a simple class which holds only properties.
  3. Inside the DataTemplate, I have some buttons that when the user clicks will reply, retweet, quote, or direct message.

The Tweet class is purely for modeling data, so adding any methods would be bad practice.  Also, since I’m in a DataTemplate I can’t easily reference another control with ElementName (in this case I need the containing parent’s DataContext).  And to add insult to injury, Silverlight 4 doesn’t have RelativeSource ancestor type.  So how do I solve this?

<StackPanel VerticalAlignment="Bottom" cal:Action.TargetWithoutContext="shell" Orientation="Horizontal">
    <Button Content="R" cal:Message.Attach="[Reply($dataContext)]" />
    <Button Content="RT" cal:Message.Attach="[Retweet($dataContext)]" />
    <Button Content="Q" cal:Message.Attach="[Quote($dataContext)]" />
    <Button Content="DM" cal:Message.Attach="[DirectMessage($dataContext)]" />

The secret is the attached property TargetWithoutContext.  As the name implies, it will set the target for all the ActionMessages attached to all the buttons, without setting the context.  If I used the Target attached property, it would set all of the Buttons’ data context to the same object – not what we want.  Since the Button’s data context remains intact, we can call “Reply($dataContext)”, which calls the Reply method on the target object (set on the StackPanel) and pass in the Tweet.  “shell” is the key of the service that I registered into the container.

Originally I wanted this entire series to be able writing a fast push data app with Silverlight and Rx, and now I’m finding that I’m writing an entire Twitter client because it’s so much fun :-).

I’m going to make another release soon.  While the first release was merely experimental, the next one will be useful enough to potentially use full time.  As you can probably tell with this blog post, it supports all the actions mentioned previously (and it’ll appear on mouse hover):


The tweet box is much improved and shows you how many character you have left:


And it’s smart enough to auto wrap http links via Twitter’s service, and the counter takes that into account.  Some interesting things to note is that in the future all links will be wrapped  Looks like Twitter is trying to eat up or something.

Clicking on @users and #topics will automatically open a new timeline and subscribe to those tweets.  It is almost full featured enough to become my main Twitter client.  There are certain features still missing, and it’s purely based on when I have time to port them over.

As always, you can install directly from here, or you can grab the code on the GitHub page!

Next post will be about Rx from a very top level perspective and how it influenced my code from beginning to be experienced and all refactorings in between.  Stay tuned!

Friday, September 16, 2011

Building a Real-time Push App with Silverlight: Part 7

Infrastructure Refactor

A lot of things changed internally, and I mean….a lot….

From an infrastructure standpoint, I decided to remove the dependency on LinqToTwitter, and I replaced it with Hammock.  A couple things led me to this decision, one being the Silverlight support wasn’t as good as I’d hoped, and the streaming API implementation was limited.  After reading the Twitter documentation I realized that the REST API was super simple and I’d be better off writing a simple interface to it.

I heard good things about Hammock, so I decided to give that one a try (I wasn’t going to go as far as reimplementing OAuth).  It was pretty easy to set up and in the end I was able to get Twitter working again and with less lines of code compared to the beginning of the refactor.


I had a couple goals for this project:

  • Learn:  I was a complete newbie to Reactive Extensions when I started but now I understand it enough to hit the ground running with it.  I’m still learning about more conventions available to Caliburn.Micro.
  • UX:  I wanted to learn a little more about interface design.  I wanted to know how little changes to gradients, shadows, colors, etc. could have a radically effect in the end result.
  • Performance:  It should be fast.  It should be able to react to real-time data.  And it should do it with low CPU utilization.
  • Concise:  I am a huge advocate for KISS.  I like convention over configuration.  I like implementing something in 2 lines of code rather than 20 (assuming it’s not cryptic).  As I was writing the app and refactoring, if there was an opportunity to remove a line of code, I did it.  The result is that the app currently consists of less than 500 lines of code as of this post (excluding XAML).


What are some interest things I learned?

  • System.Json is an amazing assembly.  All you need to do is invoke JsonValue.Parse on a string and it will create a JsonValue for you, which will be a dictionary of key/value pairs.  What’s more, by doing something like “string s = json[“text”]” will do an explicit conversion and unescape JSON characters, and only via the explicit operator.  Calling ToString(), even though converting it to a string, will not unescape.  This was completely undocumented and only found when I looked at the source code via Resharper’s external sources feature.
  • Rx is awesome.  When I ran into performance problems of trying to stream tweets from the world that contained the letter ‘a’ all I had to do was add an operator to improve the performance (in this case it was Buffer).  It should be noted that it is very important to understand what Rx is doing underneath the hood to realize its benefits.  Rx lets you refactor 30 lines of async code into 1 operator, but it’s still doing that 30 lines of code – you just don’t see it.
  • I really, really, like the conventions available from Caliburn.  Some of the features that come out of the box from this very small library saves me from writing a lot of boilerplate code like commands, triggers, and evening bindings (Caliburn will auto bind x:Name to a property).
  • Twitter’s documentation for user streams currently sucks and some trial and error was required to get it working.

What is the end result of all this effort?  We have a styled Twitter app that can update your status, pull your home/mentions timeline, and most importantly will stream all subsequent tweets.  There’s no pulling and no limits.  You will get a tweet of everyone you follow in real-time as it happens.

Moreover, there’s a feature to connect to the Streaming API to search Twitter for anything.  To get an idea of what we’re talking about, here’s a full screenshot of it:


You read that right.  I’m streaming any tweet in the world that has the words ‘and’, ‘the’, ‘yes’, or ‘no’ in them.  This is streaming around 400kB/s continuously and CPU utilization is under 25%.  The tweets are coming so fast it’s impossible to read them (at a rate of 50 tweets/second), so ideally you’d want to specify realistic search terms.

Moreover, the majority of the performance cost is actually downloading all the profile images.  If I take took out pictures I could stream any tweet in the world that has the letter ‘e’ in it at under 10% CPU.  It looks like Twitter limits the rate of tweets to 50 tweets/second because that was the rate for this one as well.

Features are minimalistic.  You can update your status, but you can’t DM, you can’t RT, you can’t do any of the normal things.  My original goal was not to write another Twitter client, but it’s actually quite fun to do so, so I’ll probably eventually get all features in.

And as promised, it’s up on GitHub, and version alpha (yes! expect bugs!!) is available in the downloads section.  Or, here’s a direct link to the XAP file on my Dropbox.  Have fun!

Tuesday, September 13, 2011

Building a Real-time Push App with Silverlight: Part 6

Back to the UI!

For this post I’m going to restyle the tweets.  Recall that they currently look like this:


The gradient background is currently #FFEEEEEE to #FFDDDDDD.  For this post I’m going to talk about a very powerful tool in a designer’s arsenal: transparency.

Your first may be to think “big deal”, but just like programmers can use base classes and injection to share common code, designers can use transparency to achieve a similar effect.

Let’s change change the color to be black, and tweak only the alpha.  I’m going to set the colors to be #11000000 to #22000000 on a white background.  This is the result:


Looks almost identical doesn’t it?  However, by doing this we have dramatically improved the reusability of the gradient.  Here’s what happens when I change the background to be a different color:


I just changed one variable to do that.  If I wanted to provide different themes for my application it would be extremely easy to do that if all the data templates were built with transparencies.  In fact, I just slap on a ColorPicker and I’d be done!

Even though it’d be easy to do this, any application that is dominated by one color gets boring very quickly. Most applications that look nice tend to focus around two dominant colors that contrast well against each other. Black and white are very common because they contrast well with a large variety of colors, but you can also have things like blue/green, purple/orange, etc.  As always, as long as you’re consistent you’ll likely have a good result.

Now, the flip side of the equation is also possible.  This is where you have something that exists already and then you put a transparent layer on top of it, creating a lightening or dimming effect.  In my experience I’ve found this to be inferior because it tends to wash out colors.  In the example above, if I applied a slightly transparent layer over top of the tweet, my picture and text would be negatively affected.  This is nonetheless a very useful trick, like with mouse over effects where you want a quick and cheap way of conveying information to the user.

Now, let’s take a big detour and restyle the entire application and go with a completely different theme.  I also wanted try something besides Apple and Microsoft inspired designs, which was more difficult than expected because I guess I’m not as creative as I thought I was :-).  Coming up with a good design takes a long time, and frequently you need some sort of inspiration.  Twitter in general is a very simple application, so the best designs are simple as well.

In an attempt to try to come up with something “cool” and “unique”, I started with the idea of elevated boxes layered on top of each other.  Here’s a before and after once I was done:


The redesign went through many iterations.  I showed it to friends and colleagues and got mixed feelings.  Some liked it.  Some thought it was too noisy.  And herein revealed a problem with complex designs – they are hard to get right!  That, and they tend to divide audience into those that really like it, and those that really don’t.

Anyways, the beauty of XAML is that I can try something else entirely without any changes to the code, so I’ll try another theme in the future.

I’m about 90% ready to release code to GitHub along with the first public alpha version.  Stay tuned!

Thursday, September 8, 2011

Building a Real-time Push App with Silverlight: Part 5

I planned on this post to be about UI, but I’m going to defer that until the next post.  I said from the start of this series that I would document about everything about building the application from scratch, including my struggles.

And with that I want to mention something that got me scratching my head one too many times.  It was with how I used LinqToTwitter.  Here is the source code which you can immediately copy/paste into a blank project to reproduce:

   1: public partial class MainPage : UserControl
   2: {
   3:    private readonly TwitterContext _context = new TwitterContext();
   4:    private readonly ViewModel _vm1, _vm2, _vm3;
   6:    public MainPage()
   7:    {
   8:        InitializeComponent();
   9:        _vm1 = new ViewModel(_context);
  10:        _vm2 = new ViewModel(_context);
  11:        _vm3 = new ViewModel(_context);
  12:        _vm1.Callback += () => Debug.WriteLine("Callback of VM1: " + _vm1.LocalState);
  13:        _vm2.Callback += () => Debug.WriteLine("Callback of VM2: " + _vm2.LocalState);
  14:        _vm3.Callback += () => Debug.WriteLine("Callback of VM3: " + _vm3.LocalState);
  16:        _vm1.Start();
  17:        _vm2.Start();
  18:        _vm3.Start();
  19:    }
  20: }
  22: public class ViewModel
  23: {
  24:    private readonly TwitterContext _context;
  25:    public event Action Callback;
  27:    public int LocalState;
  29:    public ViewModel(TwitterContext context)
  30:    {
  31:        _context = context;
  32:    }
  34:    public void Start()
  35:    {
  36:        var query = (from s in _context.Status
  37:                     where s.Type == StatusType.Public && s.Count == 10
  38:                     select s);
  39:        Debug.WriteLine("Hash code of ViewModel: " + query.GetHashCode());
  40:        query.AsyncCallback(statuses =>
  41:        {
  42:            LocalState++;
  43:            Debug.WriteLine("Hash code inside callback: " + GetHashCode());
  44:            Callback();
  45:        }).FirstOrDefault();
  46:    }
  47: }

Now, if you run this, you will see that only one of the view models will get its state updated.  Huh?!

How is that possible?  I started getting paranoid so I even added the local state variable “just in case.”

Well, I had to look into the source code of LinqToTwitter to figure out exactly what happened.  Here is the code for AsyncCallback:

public static IQueryable<T> AsyncCallback<T>(this IQueryable<T> queryType, Action<IEnumerable<T>> callback)
     (queryType.Provider as TwitterQueryProvider)
         .AsyncCallback = callback;
     return queryType;

See what happened?  The callback gets overwritten every time you call this method.  Even though the call to FirstOrDefault() causes all 3 expressions to evaluate, only the last view model will get values because that’s the with the callback attached.

Lesson of the day: The AsyncCallback extension method for LinqToTwitter is not thread-safe.

So…the question is, how do we make it thread safe?  I just replaced wrapped the AsyncCallback with another extension method:

private static readonly AutoResetEvent _twitterEvt = new AutoResetEvent(true);
public static void AsyncTwitterCallback<T>(this IQueryable<T> twitter, Action<IEnumerable<T>> callback)
    Observable.Start(() =>
        twitter.AsyncCallback(results =>
Nothing complicated – just a simple wait handle to ensure only 1 thread can go through at a time.

Hopefully upstream fixes this, or at least documents it.