Gunnar Peipman's ASP.NET blog

GridView or Repeater?

What is the difference between GridView and Repeater? This is one of the most common questions that beginners ask when they are trying to get familiar with data bound controls. Both of these controls have their own using context and I try to explain when one should use GridView and when it is okay to use Repeater.

As first thing I want to say that GridView is more complex and powerful control that offers much more functionality than Repeater. Repeater has better performance because it is not so complex and doesn't offer so rich functionality.

Repeater

Repeater is okay if you need to show data from some data source. It offers the basic rendering options: header, item, alternating item, separator and footer. It is really up to developer how to fill these templates. By example, it is easy to use Repeater to show read-only lists using templated elements.

Repeater is faster because it offers only basic data bound control rendering functionalities. If you want to show data and you don't need any complex features described below then repeater is the right joice.

GridView

GridView is rendered as table with columns and it is created to show data and let users to manipulate it. GridView offers powerful built-in features like:

  • events for sorting data when user clicks on column heading,
  • row selection,
  • row operations like adding, editing and deleting,
  • paging,
  • command columns and events to handle the commands.

GridView is excellent choice if there is a need to show tabular data and also provide users with features described above.

Some points about services layer

Some time ago I introduced here book titled as "Domain Driven Design". One concept this book described was Services Layer. Okay, there were some other layers too but I want to stop at services layer this time :)

In one of our projects we created services layer for different tasks taht can be handled as services - searching, user registering and some other types of registration tasks. At first it seems like the additional layer has no deeper point and it will be something that adds additional overhead to system (testing, documenting, deploying). But when the project was lasted some time it was clear to me that services layer was correct decision.

  1. Defining separate layer for services keeps repositories clean. I believe that repositories are not the place where complex operations should be performed. Services layer can be also separate library and if all communication goes through repositories then services layer should only know repositories interfaces to manipulate data.
  2. One thing that is maybe hard to notice in projects where one client application is written is services functionality behind pages and user controls. It is not hard to forget yourself writing and not to notice that current functionality may be useful also in multiple applications situation. When all service related code is moved to services library then forms and user controls will be clearer and deal only with functionality they have to - move data between user and server.

These were two cool points I wanted to introduce this time about using services layer. Of course, there will also other benefits and if some of them is cool I will introduce it here.

How to become a good developer?

I was asked through this blog how to become a good developers. I think this is the question that many beginners want to ask. For every question there are throusands of answers. Okay, there are many answers like these but these ones are mine. :)

  1. Attitude. Most important thing is attitude. To get strong you have to get used with an idea that for every damn day you should learn many new things. You have to understand that you are part of world that changes very fast and the only way to survive it is to study, study and study again. 
  2. Read the books. There are many great books written guys who have long experience on the field. Also there are many great books written by industry leaders. And, of course, there are too many books to read them all. Select books carefully so you don't waste your money. Read the books you got and think hard about what you have read. Is it all like this or do you have another opinion? How can you use new knowledge in your current or future task? What you made wrong in past tasks? 
     
    For guys who find books to expensive for them - there are public libraries where you can find books. Also you can check out Google books system and search for free e-Books. There are many great e-books available in internet and they are free.
     
  3. Code! Code! Code! To get a good practice write as much code you need. Try to be each time more effective than before. Study from experiences you have. Analyze the mistakes you made last time and try to find better ways how to solve these problems. Try out different features of language and platform you are using. Using different features of language you should usually write code using different patterns. This way you are improving your coding skills and also study many new things you didn't knew before.
     
  4. Try out tools and utilities that make your work easier. One part of your work is knowledge about how to make things work. The other part of your work is your development environment. Find out what features your IDE provides and look for utilities that extend it by great fetures you don't get out-of-box with your IDE.
     
  5. Try out new technologies. To stay on the track you should know about things that happened today or that will happen tomorrow. Take a time to discover new technologies and study new theories. Think about how you can use these technologies and in what context. Also try out how new stuff works and try to create something using it.
     
  6. Look how other guys develop systems. Take a look at open-source project to see how other guys build their systems. Go through the code and try to understand why they decided to do things this way and not the other. Of course, you can always communicate with authors of system if you think you have good advice how they can make their systems better.
     
  7. Everything that shines is not gold. Although there are industry leaders and veterans and their opinions matter they are just human beings like you and me. And they make mistakes - just like you and me. Of course, they are genial source of information but always use your own brain to rate the information you got.

    There are also online information sources like discussion groups, chat rooms, forums etc. Before you believe what is said there - try out. If somebody thinks that this or that thing goes this way then don't follow these opinions blind. Try out if it is this way or not. But always use your brain to analyze information.
     
  8. Participate in communities. There are many communities for Microsoft technologies. You can belong to any open community you like. Communicate with people, help them to solve their problems and ask help if you are in trouble. Also be a member of local technology communities. 
     
  9. Visit technology events. If it is possible visit technical events. There are many regions where are local .Net groups (by example INETA etc) wo organize events. Also try to visit events like TechEd and MIX. These events are valuable sources of information about new and coming technologies.

Okay, these are my nine points that I would suggest if somebody asks me how to become a good developer. If somebody feels like this list needs corrections then please drop some lines to comments sections :)

Too-Smart-Business-Object Anti-Pattern

Building up a good business library is art. Because every bad decision made early will eat project's time later. Bad decisions will also waste many time of developers who have to use this library in their work. One of the most common mistakes made is mixing DAL functionality to business objects. At first it may seems like a good idea - why not have a smart objects? - but as project goes this solution causes more and more problems. And, be warned, each next problem is worst than previous.

Well, the correct answer to this problem is n-tier architecture and design patterns (in most cases), but let's see how bad can be too smart business class. By the way, notice how hard are problems going everytime we make one step forward.

Seems like a good idea

Well, project is started and it is time to create classes for business objects. To save some coding time the team decides to make objects as smart as possible. The point is - application programmers who have a lot of work to do can use those objects and doesn't have to worry about how these objects are persisted and restored after persisting.

So, seems like this class is okay. We can modify it easily and if it is necesaary we can save this object or delete it. Very convenient.

Let's see what happens

First problem rises when somebody wants to extend one of those business classes. Methods dealing with data get override, some guys call base methods in overrides and some guys just write new logic without calling corresponding method of base class. It is done economically: let's use as much base class features as possible. Sometimes it is possible, sometimes it isn't.

Let's see what kind of trouble our guys are building and let's look at the near future. Let's see what happen three months later. The number of classes is not small anymore and there are couple of hundred business classes. Inheritance hierarchies are much longer than before and there are many problems with data access. Nobody has good picture of what is happening inside those override methods. Nobody knows what classes call base class methods and what classes have their own logic.

There are many problems related to data access and time losses are heavy. When problems were small then these problems were solved by simple hacks. Now there are hundreds of simple hacks and the code is out of control.

And even worse scenario

Let's suppose that in the beginning of project there was made one important decision about required web service: let's write the service later when business classes don't change anymore or when changes are at least very small. Now, how to show these business objects to web services? All those objects must be serializable. But how can one serialize live communication resources like database connections?

Okay, let's say that writing hundreds of DTOs is solution. Maybe it is but I doubt about it. Still there is need for wrapping business objects because it is not possible to send them over network. And this wrapping maybe pretty expensive job to do for server.

This storty ends with web service hack because there is not time enough to rewrite business layer from the ground. There is time for fast hacks but who guarantees that these hacks will work?

Be careful when you are making decisions about system architecture and design. If something seems very smart then check it over many times to make sure you don't create the small problem that grows larger exponentially in time.

Avoiding exceptions using list controls

Avoiding excpetions is always a good practice because exceptions can hurt as when thay occure. They may cause also hard performance loss. Assigning selected value to list controls is one candidate for ArgumentOutOfRange exceptions. Often this problem is solved using unhandled exception:


try
{
    cboServiceGroup.SelectedValue = group.Id.ToString();
}
catch
{
    ; 
}

To avoid this exception we can check out if value exists in list before we assign it to list control.


if(cboServiceGroup.Items.FindByValue(group.Id.ToString()) != null)
{
    cboServiceGroup.SelectedValue = group.Id.ToString();
}

This way we will avoid a lot of exceptions in our code when we are writing user interfaces where lists are widely used.

DTO - not only for web services

Usually developers think that DTO (Data Transfer Object) is something related to web services where data serialization is required to move data from one point of network to another. It is clear that in most cases there is no point to move complex data structures over network when client side needs this data in pretty simple form. That's why DTOs are created - they are simple, easily serializable and there is no data that client side doesn't need. But there are also other DTOs you may find useful.

User Interface DTOs

User Interface (UI) may also need some DTOs. By example, data bound controls try usually to save bounded data to their ViewState. But what happens when data source is list on some objects and not DataTable as we can usually see from beginner tutorials? DataTable is serializable and therefore it is easy to save DataTable to ViewState. But objects are often not marked as serializable and binding them to data bound controls may cause exceptions.

This problem can be solved using DTOs. We can create DTOs as flat objects that are serializable. They doesn't contain any child objects - only properties with their values. We can wrap source data to DTOs and bind list of these DTOs to our data bound controls.

Search criteria DTOs

In one of our current project we are using some DTOs to define search criterias. These DTOs are also flat ones because they store only ID-s of search conditions, string tokens and dates. There is one main search DTO and some internal search DTOs. This far we are happy with this solution because if we design those DTOs carefully they are very easy and convenient to use in client code.

Search sitemap DTOs

ASP.NET Futures has support for search engine sitemaps (follow this reference to take a look at the code examples). To let it create a search engine sitemap for products you must define class for products that has specific attributes required by sitemap generating system. This object is also simple DTO because it has no complex attributes.

I am sure that there are many more DTOs, these three were just examples of some additional DTOs besides DTOs we are using with web services. Okay, and as a last word - DTO is design pattern refered also to as Value Object in Sun.

Sometimes integration tests are more important

There are some cases when integration tests are more protective than unit tests. Of course, there is no reason to compare these two kinds of tests but if we have to write them we have to set priorities and think what problems may arise during development. One special case when it is important to have integration tests early in place is when we are using O/R-mappers.

Errors in mapping files, database and data differences in business logic of classes and corresponding database tables are time consuming to track, debug and solve. These issues may raise unexpectedly for younger programmers as they often don't think "too far". When we have tests in place for this kind of problems we are able to detect and solve these problems faster.

Example

Suppose you have some beginner programmers in your team (or some thunderheads who have lived with chaos in their mind right after they were born). One of those guys writes mapping files for O/R-mapper. Some other guy creates database objects like tables, views and stored procedures. And somebody writes business classes and their validation logic. Three persons - three points where things may go wrong.

When everybody is done the tests are performed. Everything seems to be correct in the scope of first release. Now customer gets notice that he or she or it (in the case when customer is UFO) can test the system. After five minutes customer sends screenshot with nasty server error telling that mapper is not able to perform delete operation. How and why this problem came suddenly?

Okay, under special conditions there were some rows added to table that is topic of next iteration. Because this table seemed therefore not so important for beginners they just created it and added some basic mappings but not cascading operation rules. In the database there are relations but no cascades defined because customer wanted to be able to use different databases. Why tester noticed nothing? Because tests related to this one table were topic of next iteration.

Okay-okay, I already hear the voices in internet through my network cable screaming that no normal company has such a problems and other blah-blah-blah like this. But hey, don't forget that we are only human beings and we are very able to make mistakes and forget important things.

How to avoid problems like this

If you want to be correct and forward-looking developer you will write a load of integration tests or if you are lazy then you will write one big test. In both cases you try to do the following:

  • Check out if you can insert objects. Test if you can create and save new object without errors. After inserting you have to test if all data you wanted to save is really saved or not.
  • Check out if you can update objects. Test if you can save changes made to objects data with out errors. And also check out if changes were really saved.
  • Check out cascade deletes. Add couple on rows on every table and try to delete top level object of each cascading branch.

Of course, there are much more things one may find protective and add to this list, but these three tests are the basic ones you should try out.

Searching problems in mapping files and database is time consuming activity. It is better to create mappings and database objects correctly on the first time. This way you can save a lot of time for another important tasks in project.

Some extension methods for DateTime

During one of my current projects I wrote some useful extension methods for DateTime class. I had to write custom calendar component and therefore I needed manipulate dates a little bit. Here is some extensions I would like to share with you. And, of course, comments and suggestions are welcome as always.

Why chose extension methods? Because there is always current date given for calendar. Even when activities in calendar are based on months there is always current date. So I wrote those methods in current state context.

Get first date of current month


public static DateTime GetFirstDateOfMonth(this DateTime currentDate)
{
    return currentDate.AddDays((-1)*currentDate.Day + 1);
}

Get last date of current month


public static DateTime GetLastDateOfMonth(this DateTime currentDate)
{
    return currentDate.AddMonths(1).GetFirstDateOfMonth().AddDays(-1);
}

Get dates array from current date to given date

I think that for common use it is better to make this method as static method of some helper or utility class. Then it more clear that one can use it with any date range. Also it is possible to create one overload for this class that accepts TimeSpan as argument.


public static DateTime[] GetDatesArray(this DateTime fromDate, DateTime toDate)
{
    int days = (toDate - fromDate).Days;
    var dates = new DateTime[days];
 
    for(int i=0; i<days; i++)
    {
        dates[i] = fromDate.AddDays(i);
    }
 
    return dates;
}

Get all date array for current calendar view

This method creates array that contains all dates in current month's calendar view. If first day of month is tuesday then last day from previous month is also added to array to fill up the first monday in calendar. If last day of month is friday then two days from next month are also added to array to fill saturday and sunday slot.

NB! This method is very raw and it is not completely tested yet. So I cannot be 100% sure if i contains errors or not. The nasty hack here is changing week day number to make monday as first day of week (sorry, I live in this kind of region).


public static DateTime[] GetCalendarMonthDatesArray(this DateTime currentDate)
{
    var first = currentDate.GetFirstDateOfMonth();
    var firstWeekDay = (int)first.DayOfWeek;
    if (firstWeekDay == 0)
        firstWeekDay = 7;
 
    var from = first.AddDays((int)DayOfWeek.Monday - firstWeekDay);
    var last = currentDate.GetLastDateOfMonth();
    var lastWeekDay = (int)last.DayOfWeek;
    if (lastWeekDay == 0)
        lastWeekDay = 7;
 
    var thru = last.AddDays(lastWeekDay - (int)DayOfWeek.Monday + 1);
    return from.GetDatesArray(thru);
}

So, what else I have to say? Happy extending! :)

Posted: Jul 16 2008, 10:20 PM by DigiMortal | with 9 comment(s)
Filed under:
Domain Driven Design

domain-driven-design I am sure you have all read this book and this book needs no further introduction - Domain Driven Design by Eric Evans! I readed this book couple of months ago and now I am trying to apply good ideas I got from this book. Instead of writing usual introduction I tell you a little bit about my experiences when applying ideas represented in this book.

Before I start I mention quickly that Domain Driven Design has only few code examples. To be honest I expected more but this is not a problem - there are many other books that cover design practices on more technical level. Most of this book describes ideas about systems architecture and design. It covers smaller systems and also larger systems that are built by separate teams maybe even in separate geographic locations. The mind framework this book gives is mighty. At least for me. Although first chapters of this book are a little bit dry and boring the further is very interesting. So, survive the first chapters and read this book to the last page.

After reading Domain Driven Design we tried to apply new knowledge in one of our systems we are building currently. There are some points that work very well (don't repeat me if you haven't read this book):

  1. Using services layer is very good approach because it keeps repositories clean of complex logic behind services. If services layer is not small then it is good idea to separate services and repositories.
  2. Using infrastructure layer is also good approach because this is the way how to keep different base services in separate library that is easy to switch to other if there is a need for it.
  3. Driving communication between subdomains only through subdomain's main objects gives another advantage: it makes communication flow between objects very clear. There are less grey spots of responsibility and therefore less ways how to break things.

Of course, there are many other good points you can find from this book when you read it. Three points above gave just an example about how to apply Eric's ideas.

Silver bullet anti-pattern

I will continue my little serie about anti-patterns of decisions and activities that may screw up projects and make developers (and why not also others) life hell. Now let's look at silver bullet anti-pattern. It is about using unknown tools and technologies in the place where one shouldn't never do that.

Okay, suppose you start with a larger project and you have one week of analysis and design meetings behind. Your team must use some new technology but it is okay because most of your developers have used it and you have also some more experienced developers on that technology. Everything seems okay and everybody is full of power to build up a new killer solution.

Now, about third week, there is meeting where one guy introduces new idea - why not to use related technology XYZ? He tells that he has even book covering that technology, it is about 800 pages - average programming book - and this technology looks very promising. At least introductions found from internet suggest this new related technology. Because this new technology looks promising and it seems that this technology solves many problems you say okay, let's use it - team has found the silver bullet for this project.

After two months you feel that this bullet is not so silver anymore and also you feel like this bullet is shot to your head. Project is out of schedules, there are weird problems related to technology XYZ, it is not easy to find any documentation or other helping stuff about it and nobody knows when project may get back to track.

It is always good to remember: if you want a silver bullet you will get it straight between your brains.

More Posts Next page »