Professional Enterprise .NET

Published by

Wiley Publishing, Inc.

10475 Crosspoint Boulevard

Indianapolis, IN 46256

www.wiley.com

Copyright © 2009 by Wiley Publishing, Inc., Indianapolis, Indiana

Published simultaneously in Canada

ISBN: 978-0-470-44761-1

No part of this publication may be reproduced, stored in a retrieval system or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, scanning or otherwise, except as permitted under Sections 107 or 108 of the 1976 United States Copyright Act, without either the prior written permission of the Publisher, or authorization through payment of the appropriate per-copy fee to the Copyright Clearance Center, 222 Rosewood Drive, Danvers, MA 01923, (978) 750-8400, fax (978) 646-8600. Requests to the Publisher for permission should be addressed to the Permissions Department, John Wiley & Sons, Inc., 111 River Street, Hoboken, NJ 07030, (201) 748-6011, fax (201) 748-6008, or online at http://www.wiley.com/go/permissions.

Limit of Liability/Disclaimer of Warranty: The publisher and the author make no representations or warranties with respect to the accuracy or completeness of the contents of this work and specifically disclaim all warranties, including without limitation warranties of fitness for a particular purpose. No warranty may be created or extended by sales or promotional materials. The advice and strategies contained herein may not be suitable for every situation. This work is sold with the understanding that the publisher is not engaged in rendering legal, accounting, or other professional services. If professional assistance is required, the services of a competent professional person should be sought. Neither the publisher nor the author shall be liable for damages arising herefrom. The fact that an organization or Web site is referred to in this work as a citation and/or a potential source of further information does not mean that the author or the publisher endorses the information the organization or Web site may provide or recommendations it may make. Further, readers should be aware that Internet Web sites listed in this work may have changed or disappeared between when this work was written and when it is read.

For general information on our other products and services please contact our Customer Care Department within the United States at (877) 762-2974, outside the United States at (317) 572-3993 or fax (317) 572-4002.

Wiley also publishes its books in a variety of electronic formats. Some content that appears in print may not be available in electronic books.

Library of Congress Control Number: 2009933374

Trademarks: Wiley, the Wiley logo, Wrox, the Wrox logo, Wrox Programmer to Programmer, and related trade dress are trademarks or registered trademarks of John Wiley & Sons, Inc. and/or its affiliates, in the United States and other countries, and may not be used without written permission. All other trademarks are the property of their respective owners. Wiley Publishing, Inc. is not associated with any product or vendor mentioned in this book.

Dedicated to my wife Andrea, whose kindness, imagination, beauty, and patience make her the girl every man hopes to marry.

—Jon Arking

Dedicated to my beautiful Lynsey — thanks for the love, tea and the toast. And for Agatha and Columbo . . . probably the best rabbits in the world.

—Scott Millett

About the Author

Jon Arking is an enterprise software architect working in the greater Philadelphia region. He has been designing, developing, and managing multi-tiered systems for over 14 years, specializing in system migrations and the design of distributed architectures. Jon has experience programming in multiple languages and platforms, and has spent much of his career designing systems, managing teams, teaching classes, giving lectures and interviews, and publishing on a variety of technical topics. His company, Arking Technologies, specializes in designing enterprise systems for large companies in the Philadelphia area.

Scott Millett lives in Southsea, Portsmouth in the South of England where he is the senior developer for Wiggle.co.uk, an e-commerce company specializing in cycle and tri athlete sports based in the UK. He has been working with .NET since version 1.0 and has earned the Microsoft Certified Professional Web Developer certification. He is a regular contributor to the asp.net forums and when not writing about or working with .NET he can be found relaxing and enjoying the music at Glastonbury and all of the major music festivals in the UK during the summer. If you would like to talk to Scott about the book, anything .NET or the British music festival scene, then feel free to write to him at scott@elbandit.co.uk, or visit his blog at www.elbandit.co.uk/blog.

Credits

Acquisitions Editor

Paul Reese

Project Editor

Ed Connor

Technical Editor

Doug Parsons

Production Editor

Kathleen Wisor

Copy Editor

Foxxe Editorial Services

Editorial Director

Robyn B. Siesky

Editorial Manager

Mary Beth Wakefield

Production Manager

Tim Tate

Vice President and Executive Group Publisher

Richard Swadley

Vice President and Executive Publisher

Barry Pruett

Associate Publisher

Jim Minatel

Project Coordinator, Cover

Lynsey Stanford

Proofreader

Jen Larsen, Word One

Josh Chase, Word One

Indexer

Robert Swanson

Cover Image

© Digital Vision/Punchstock

Acknowledgments

I owe a lot of thanks to many people for helping to make this book a reality. Thanks to Ed Connor and Jim Minatel for their patience and understanding during a very busy time in my career. Huge thanks to my coauthor, Scott, for understanding my vision and helping to bring it to life. If you ever make it to Philly I’ll have to show you how we roll on this side of the Pond! Thanks also to Vince, Sandra, John, and Ed at the Jug Handle Inn, who let a guy write a book at the bar on late Saturday nights. A special note of gratitude to my lovely mother, whose nagging and drama always kept me on course, and to my father who clearly helped shape me into the cantankerous, overbearing geek/meathead I am today. Most of all, thanks to my wife Andrea, and my children, Emma and Jake, who once again proved that their patience for me has no bounds!

—Jon Arking

First thanks to Jim Minatel at Wiley for giving me the opportunity of writing for Wrox and suggesting me to Jon. Thanks to Jon for the chance to get involved on such a great project and for all the help, support and guidance during the writing process. The next time you’re in England I will take you on a good old fashioned pub crawl! Thank you to Doug Parsons, the technical editor, for all of his hard work and a big thanks to Ed Connor who had the unenviable task, as the book’s Project Editor, to keep myself and Jon on track — thank you for all of your help. Finally special thanks to Lynsey, my beautiful wife to be for all the love and support you have given me before, during, and since writing this book and for reminding me what’s important in life.

—Scott Millett

Introduction

Computer programming and developing business software are not the same thing. Though many think that writing code is the same no matter how you do it or who you do it for, nothing could be further from the truth. Sure, you’ve got to have coding skills in order to land some of those fancy, big-paying gigs, but that’s just the beginning. Nowadays, creating software for businesses requires knowledge of many different languages and disciplines. It requires both low-level programming skills along with higher-level, comprehensive design experience. Most of all, it requires patience and tolerance of new ideas.

Of course, there are plenty of people out there who don’t agree with us. Most of us know at least one or two programmers who do their best work locked away in a geek closet, insulated from the complexities of the business world. That’s fine for some. After all, not everyone wants to build software that makes their whole company sing. Small application development will always have its rightful place in the community. Yet grow some of those applications into large, enterprise systems, and you’re sure to run into trouble. More often than not, the small app development approach delivers wonderfully in the short term, then bites back hard as you expand its use and feature set. That’s why when it comes to building company-wide enterprise systems, knowledge of enterprise design goes a long way.

The struggle for well-designed systems is far from new. Since the dawn of the computer age IT professionals have been debating how to strike a compromise between rapid application development and sound software design. It’s a veritable tug-o-war between the best of design intentions and the very demanding hand that feeds you. Yet as businesses become more IT-savvy, they have begun investing in enterprise design with the hope that upfront costs will save money down the line. While the possibility of that is entirely real, developers need to know how to apply enterprise patterns correctly, in a manner best suited for their clients.

Microsoft developers are familiar with this argument. A platform almost exclusively dedicated to rapid application development, Microsoft applications have long been riddled with poor design, exchanging extensibility and flexibility for quick time-to-market. As enterprise methodologies become more widely embraced, a new generation of Microsoft developers find themselves faced with the daunting task of learning these new patterns and incorporating them into their existing skill sets and applications. This unfortunate gap between building well-designed applications and the high demand for rapid delivery has plagued the Microsoft community for years. With so many new enterprise patterns to learn, Microsoft programmers are in need of a practical resource to help guide them through each, and help them understand the best ways to update their own code and programming practices.

Enter Professional Enterprise.Net — the definitive guide for Microsoft programmers interested in learning the latest enterprise development methodologies. Our goal for this book is to educate developers on the different patterns and methodologies that can help to make their code cleaner, and more maintainable. It strives to provide a roadmap for mid-level and senior-level Microsoft programmers looking to migrate both their applications, as well as their own skill sets to newer, more flexible enterprise methodologies.

What This Book Covers

This book is meant to serve as an introduction to some of the more popular software development patterns and methodologies. It is intended for those with some background in Microsoft application development and is especially geared towards people with C# and ASP.NET development experience. This book does not intend to be a definitive all-in-one resource for all things enterprise. Enterprise design is an extremely broad subject, covering topics that warrant their own set of books and resources. Instead, this book provides a comprehensive look into a handful of widely embraced subjects. Readers looking for deep coverage of subjects such as Test Driven Development, middleware design patterns, or web MVC using ASP.NET would do better to find books dedicated to these topics exclusively. Beginning with a discussion on enterprise concepts and continuing through testable code methodologies and design patterns, you will first become familiar with some of the different ways to assemble your code in a loosely coupled, testable manner. Subsequent chapters delve into some of the tools that embrace these methodologies, such as Spring.Net, nHibernate, and ASP.NET MVC. The combination of these subjects will help to educate developers on the ways these different patterns work together, ultimately helping them to decide which pieces or portions are best suited for their business. Although this book does tell a story, it is also intended to be a useful reference for aspiring enterprise developers. Each chapter has been designed to stand on its own, without requiring the reader to first read all preceding chapters beforehand. With that in mind, here is a chapter-by-chapter synopsis:

Chapter 1: What Is Enterprise Design?

We begin by discussing some of the concepts at the core of enterprise development. These concepts have less to do with the physical act of coding and more to do with the spirit behind enterprise design and why we strive to embrace it. It begins with the concept of enterprise architecture, taking time to define what that means and to whom it applies. The reader then begins to explore the concept of enterprise development, focusing primarily on its core values, such as reliability, maintainability, and the separation of concerns. Then the chapter moves into some of the history of software design, walking the reader through the evolution of the core values. The chapter concludes with a discussion of some of the popular tools enterprise developers have come to embrace.

Chapter 2: The Enterprise Code

Chapter 2 introduces some of the new coding concepts germane to enterprise development. Concepts such as modularity and loose coupling are explained in detail, accompanied with some simple code samples to help demonstrate the concepts. Unit testing is a strong driving force in enterprise architecture, and it is carefully explained within the context of modularity and loose coupling. Inversion of Control is also introduced here, and it is explained how the creation of object instances can be made manageable within the rubric of a testable code base. The chapter concludes with a discussion of some of the tools available to help aid in enterprise coding, such as NUnit, Resharper, and Spring.Net.

Chapter 3: Emancipate Your Classes

Chapter 3 focuses on the concept of Dependency Inversion. This principle inverts the relationship between high level and low level modules, reducing their reliance on concrete implementations. The chapter ends with an application of the DI principle in the form of Dependency Injection, which is the process of injecting low-level objects into the higher-level objects.

Chapter 4: Test Driven Development

Chapter 4 introduces the Test Driven Development methodology, a development pattern that facilitates the design of loosely coupled, highly testable code. Using a comprehensive example, TDD is used to demonstrate how an application’s design can be driven via unit tests. The chapter also covers the process of creating unit tests, discussing the compromise between a purist’s approach to TDD and the practical application of the methodology.

The chapter concludes with a focus on unit testing modules with dependencies on expensive resources. The concept of mocking and stubbing is introduced, with an example using a popular mocking and stubbing framework.

Chapter 5: Make It Simple Again

Chapter 5 revisits the concepts introduced in Chapter 3, focusing on some of the tools and patterns that help to make enterprise development easier. After discussing the pros and cons of the Factory and Service Locator, you are introduced to the Inversion of Control principle, an abstract principle describing designs in which the flow of a system is inverted in comparison to procedural programming. The chapter ends with a simple build-your-own Inversion of Control container and a brief review of a popular open source product called Structure Map.

Chapter 6: Getting to the Middle of Things

Moving away from the core concepts and coding fundamentals germane to enterprise development, the reader now moves into the patterns portion of the book. Here, we discuss some of the popular design patterns and available frameworks for building a well-designed enterprise system. This first chapter tackles the concept of middleware. It begins with a look at the history of tiered design, starting from the legacy model of mainframe systems and moving through client-server architectures and web development. The chapter then explores some of the popular design patterns that are used in distributed systems today, such as services and message-oriented middleware.

Chapter 7: Writing Your Own Middleware

Chapter 7 focuses on the business logic contained with an application.

You will read about three popular middleware patterns: Transaction Script, Active Record, and the Domain Model pattern. You will then briefly explore Domain Driven Design, a design methodology currently gaining a notable degree of popularity. This emerging pattern focuses on the business logic of an application, strongly separating technical infrastructure concerns.

Chapter 7 ends with the building of a Domain Model for a fictitious Mortgage Loan Approval application, a project that will be reused in later chapters. Using some of the core principles of Domain Driven Design, you will walk through gathering requirements, talking to domain experts, and building a Domain Model using Test Driven Development principles.

Chapter 8: Mining Your Own Business

Chapter 8 addresses the concept of persistence. The chapter opens with a brief discussion on the responsibilities of the data access layer, and the traditional approach to hand-rolling with ADO.NET. The Object Relation Mapper is then introduced, followed by a discussion of the advantages and disadvantages of using a framework rather than doing it yourself.

You will then read about two methods of persistence management. The first is a data model approach using Microsoft’s LinqToSQL. The second is a pattern that uses Microsoft’s Entity Framework Object Relation Mappers with a pattern called the Data Access Object pattern.

Chapter 8 concludes with the provisioning of the Mortgage Loan Approval application created in Chapter 7 with a Repository layer built using nHibernate.

Chapter 9: Organizing Your Front End

Continuing with our exploration of system design, this next chapter explores the world of user interface development. Like Chapter 6, we begin with a discussion of the history of user interface design and programming. The reader is introduced to some of the influences of rapid application design and some platform tools that were available to support it. Moving through the period of drag-and-drop screen design and into web programming, we discuss some of the more popular emerging design patterns that eventually made their way into enterprise systems, such as the Model-View-Controller pattern.

Chapter 10: The Model-View-Presenter Pattern

Chapter 10 jumps squarely into user interface (UI) design with an in-depth review of the Model-View-Presenter pattern. Creating a testable user interface requires a loosely coupled pattern. However, applying such patterns to older user interface code can be difficult to do without breaking the application. The right pattern would enable unit testing on user interface code without being overly intrusive. Such is the goal of the Model-View-Presenter pattern. Arguably one of the most popular patterns used for enterprise user interface design, the Model-View-Presenter pattern helps to separate interface code from the visible artifacts themselves. Chapter 10 explains this pattern in detail, walking you through the individual components, explaining their interaction, and reviewing the various aspects of testability they provide. The chapter provides a detailed code sample of a simple mortgage calculator built using the Model-View-Presenter pattern, targeting both web and thick client platforms for demonstrative purposes.

Chapter 11: The Model-View-Controller Pattern

Following the themes outlined in Chapters 9 and 10, this chapter takes a deep dive into the Model-View-Controller pattern. A brief review of the history of this pattern is revisited, with an emphasis on the Ruby on Rails framework and the impact it has had. The reader is introduced to ASP.NET MVC, the web Model-View-Presenter pattern recently released by Microsoft for developing web applications on the Windows platform. This is followed with a detailed discussion of the core components and behaviors that the model exposes. We review the pros and cons of the web MVC model, with particular comparisons made with the Model-View-Presenter pattern introduced in Chapter 10. The chapter then moves into an aggressive code sample using the Mortgage Loan Model introduced in Chapters 7 and 8 and referenced again in Chapter 10.

Chapter 12: Putting It All Together

The book concludes with a comprehensive sweep of all concepts, methodologies, and design patterns discussed in all of the previous chapters. Taking a step back to the core values introduced in Chapter 1, a brief revisiting of each chapter is realized, summarizing the key points each chapter delivered and relating them to broader enterprise goals. We discuss how to apply the right pattern for the right type of system, picking only the frameworks and models suitable for a system’s requirements. The chapter concludes with a brief walkthrough of a broad, multifaceted mortgage application that uses most of the themes and patterns explored in the book.

How This Book Is Structured

Professional Enterprise .NET is meant to be used as both a step-by-step guide as well as a continuous source of reference. The book is broken into distinct sections which can be read either as a whole, or piecemeal. The first portion of the book, Part I, addresses the philosophy behind enterprise development. Part II is a deeper discussion of coding patterns. It covers the concept of loose coupling, the best ways to decouple existing code, and the benefits of Test Driven Design. The third and final section, Part III, is a broad review of some of the more common design patterns used in enterprise systems. It reviews popular ways to structure your middleware, takes you through data minimizing and persistence techniques, and provides some background on enterprise UI design. Each chapter begins with an explanation of the subject matter, and most are complemented with a thorough code sample. Code samples can be reviewed on their own, or they can be assessed together for a more holistic system assessment.

Conventions

To help you get the most from the text and keep track of what’s happening, we’ve used a number of conventions throughout the book.

Notes, tips, hints, tricks, and asides to the current discussion are offset and placed in italics like this.

As for styles in the text:

We highlight new terms and important words when we introduce them.

We show keyboard strokes like this: Ctrl+A.

We show file names, URLs, and code within the text like so: persistence.properties.

We present code in two different ways:

We use a monofont type with no highlighting for most code examples.

We use gray highlighting to emphasize code that is of particular importance in the present context.

Source Code

As you work through the examples in this book, you may choose either to type in all the code manually or to use the source code files that accompany the book. All of the source code used in this book is available for download at www.wrox.com. Once at the site, simply locate the book’s title (either by using the Search box or by using one of the title lists) and click the Download Code link on the book’s detail page to obtain all the source code for the book.

Because many books have similar titles, you may find it easiest to search by ISBN; this book’s ISBN is 978-0-470-44761-1.

Once you download the code, just decompress it with your favorite compression tool. Alternately, you can go to the main Wrox code download page at www.wrox.com/dynamic/books/download.aspx to see the code available for this book and all other Wrox books.

Errata

We make every effort to ensure that there are no errors in the text or in the code. However, no one is perfect, and mistakes do occur. If you find an error in one of our books, like a spelling mistake or faulty piece of code, we would be very grateful for your feedback. By sending in errata you may save another reader hours of frustration and at the same time you will be helping us provide even higher quality information.

To find the errata page for this book, go to www.wrox.com and locate the title using the Search box or one of the title lists. Then, on the book details page, click the Book Errata link. On this page you can view all errata that has been submitted for this book and posted by Wrox editors. A complete book list including links to each book’s errata is also available at www.wrox.com/misc-pages/booklist.shtml.

If you don’t spot “your” error on the Book Errata page, go to www.wrox.com/contact/techsupport.shtml and complete the form there to send us the error you have found. We’ll check the information and, if appropriate, post a message to the book’s errata page and fix the problem in subsequent editions of the book.

p2p.wrox.com

For author and peer discussion, join the P2P forums at p2p.wrox.com. The forums are a Web-based system for you to post messages relating to Wrox books and related technologies and interact with other readers and technology users. The forums offer a subscription feature to e-mail you topics of interest of your choosing when new posts are made to the forums. Wrox authors, editors, other industry experts, and your fellow readers are present on these forums.

At http://p2p.wrox.com you will find a number of different forums that will help you not only as you read this book, but also as you develop your own applications. To join the forums, just follow these steps:

1. Go to p2p.wrox.com and click the Register link.

2. Read the terms of use and click Agree.

3. Complete the required information to join as well as any optional information you wish to provide and click Submit.

4. You will receive an e-mail with information describing how to verify your account and complete the joining process.

You can read messages in the forums without joining P2P, but in order to post your own messages, you must join.

Once you join, you can post new messages and respond to messages other users post. You can read messages at any time on the Web. If you would like to have new messages from a particular forum e-mailed to you, click the Subscribe to this Forum icon by the forum name in the forum listing.

For more information about how to use the Wrox P2P, be sure to read the P2P FAQs for answers to questions about how the forum software works as well as many common questions specific to P2P and Wrox books. To read the FAQs, click the FAQ link on any P2P page.

Setting Expectations

If you are a proficient, hard-blogging, forum-surfing open source guru, put this book down right now. This book is not a definitive resource for all things enterprise. It doesn’t demand perfect Test First methodologies. It doesn’t tout the Agile Manifesto at every turn, and it won’t appeal to the enterprise perfectionists.

It is a book intended to introduce readers to the merits of good system design and how to apply it to large system projects. While we certainly don’t want to incur the wrath of the enterprise/open source community, it is important to note that this book targets the other side of programming community. Our intention is to provide a simpler, less-rigid preface to modern software design principles. Although the book is tailored to Microsoft programmers, it is important to understand that the practices and methodologies discussed apply to all software development in any technical environment. Many of the tools and frameworks used have come from other development platforms, such as Java and Ruby on Rails. Some of these tools also come from Microsoft, but their mention in this piece has little to do with supporting the “Mother Ship” in Redmond and everything to do with good software design. The authors of this book are active supporters of the open source community. Both believe strongly that the best solution to a problem doesn’t always come from the same company.

Over the next few months, you’re bound to find lots of books on similar topics, many of which are dedicated to pitching a Microsoft solution. This book is about understanding the nature of good system design first and then choosing the path that best suits your needs. We’ll be discussing some of the strong points of Microsoft technologies, as well as some of the notably weak ones. Understanding the pros and cons of the different tools that are available will help you make better decisions for your projects and ultimately lead to better system design.

Part I: Introduction to Practical Enterprise Development

Chapter 1: What is Enterprise Design?

Chapter 2: The Enterprise Code

Chapter 1

What is Enterprise Design?

“Mr. Arking, your experience, certifications, and references are terrific, but unfortunately we can’t hire you. Your resume just doesn’t have enough enterprise experience . . . .”

That was the first time I had ever heard the word “enterprise.” Wrapped subtly within a casserole of deprecating niceties and empty affirmations, assailing my staunch sense of geek-honor as I wrestled with the gravity of the moment. That was the first time I was ever turned away from a job in software development. Like most fallen nerds, I went through the normal stages of post-interview withdrawal. Similar to the departing of a close friend or relative, I felt denial, then outrage, then moved slowly into a state of grief. As the eccentric side of me skimmed through the torrent of emotions that accompany job overreaction, I began to evaluate what I did wrong. I have no enterprise experience? What does that mean? Didn’t my interviewers read my resume? Weren’t they impressed with my vast experience with different APIs? Didn’t they appreciate my deep knowledge of different platforms and languages? I mean, look at all of the companies I worked for . . . all of the different applications I had built! Surely some of that demonstrated hands-on practice with enterprise!

After my failed interview I was determined to figure out what I had missed. I prided myself on being the consummate interviewee. I had all the right answers, knew all the best programming tricks. I had stacks of code samples and lots of great references to back up my work. I had to know where it all went wrong. My investigations inevitably led me back the job description which, among a great many requirements, listed the following work experience:

Ideal candidate will have extensive exposure to enterprise architecture, with a background in designing large systems for multifaceted, heterogeneous platform support.

At first glance, this requirement didn’t seem like much. Yet there must be something more to it than I was grasping. Multifaceted, heterogeneous platform support? What was that all about? I began to investigate what the employer meant by “enterprise patterns,” expecting to find some subtlety of coding that I had likely touched on in one way or another. However, when I looked up enterprise architectures online, I was stunned to find a whole new level of design, one that had completely eluded me for over 8 years of computer programming. I took a good look at my resume and began to understand that I was a horrible fit for the position. I had built some great applications, but that’s all they were: applications. Some of the things I had developed were very impressive, requiring a lot of knowledge in coding and multi-tiered design. Still, I had never actually developed an enterprise system. I had never designed an infrastructure or set of processes for other developers in other areas to support. I had never participated in an architectural process, never wrote tests before I wrote my code. I hadn’t ever established patterns and practices to support a broad context of business needs. In fact, I had little or no experience in all of the key concepts behind all things enterprise.

I had no enterprise experience. Despite the fancy software that I had spent my career building, I hadn’t even so much as dabbled in the enterprise fray. Like a great many before me, I had fallen prey to the enterprise assumption that haunts even the fanciest computer programmer. I presumed that if I’ve programmed enough powerful software, and learned everything there is to learn about platform libraries, APIs and SDKs, then I have earned the right to call myself an enterprise developer. Not only is this assumption wrong, it is a widely accepted assumption in Microsoft programming community. Unfortunately, I had to learn that the hard way.

And so it began, my long journey into the world of enterprise architecture and development. Wiping away all preconceived notions of what software development was supposed to be, I immersed myself into the very culture of enterprise architecture. I read books on different development processes. I purchased trade magazines and followed articles dedicated to large system development. I subscribed to countless blogs and forums published by some of the biggest players in the enterprise community. I went enterprise native, if you will. The result was a complete retooling of my skills, and a revision of my approach to software design.

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!